aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/hardware
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/isdn/hardware
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/isdn/hardware')
-rw-r--r--drivers/isdn/hardware/Kconfig10
-rw-r--r--drivers/isdn/hardware/Makefile6
-rw-r--r--drivers/isdn/hardware/avm/Kconfig66
-rw-r--r--drivers/isdn/hardware/avm/Makefile11
-rw-r--r--drivers/isdn/hardware/avm/avm_cs.c510
-rw-r--r--drivers/isdn/hardware/avm/avmcard.h585
-rw-r--r--drivers/isdn/hardware/avm/b1.c814
-rw-r--r--drivers/isdn/hardware/avm/b1dma.c980
-rw-r--r--drivers/isdn/hardware/avm/b1isa.c245
-rw-r--r--drivers/isdn/hardware/avm/b1pci.c417
-rw-r--r--drivers/isdn/hardware/avm/b1pcmcia.c224
-rw-r--r--drivers/isdn/hardware/avm/c4.c1310
-rw-r--r--drivers/isdn/hardware/avm/t1isa.c596
-rw-r--r--drivers/isdn/hardware/avm/t1pci.c260
-rw-r--r--drivers/isdn/hardware/eicon/Kconfig53
-rw-r--r--drivers/isdn/hardware/eicon/Makefile23
-rw-r--r--drivers/isdn/hardware/eicon/adapter.h17
-rw-r--r--drivers/isdn/hardware/eicon/capi20.h699
-rw-r--r--drivers/isdn/hardware/eicon/capidtmf.c685
-rw-r--r--drivers/isdn/hardware/eicon/capidtmf.h79
-rw-r--r--drivers/isdn/hardware/eicon/capifunc.c1219
-rw-r--r--drivers/isdn/hardware/eicon/capifunc.h40
-rw-r--r--drivers/isdn/hardware/eicon/capimain.c147
-rw-r--r--drivers/isdn/hardware/eicon/cardtype.h1098
-rw-r--r--drivers/isdn/hardware/eicon/cp_vers.h26
-rw-r--r--drivers/isdn/hardware/eicon/dadapter.c366
-rw-r--r--drivers/isdn/hardware/eicon/dadapter.h34
-rw-r--r--drivers/isdn/hardware/eicon/dbgioctl.h198
-rw-r--r--drivers/isdn/hardware/eicon/debug.c2133
-rw-r--r--drivers/isdn/hardware/eicon/debug_if.h90
-rw-r--r--drivers/isdn/hardware/eicon/debuglib.c156
-rw-r--r--drivers/isdn/hardware/eicon/debuglib.h322
-rw-r--r--drivers/isdn/hardware/eicon/dfifo.h54
-rw-r--r--drivers/isdn/hardware/eicon/di.c835
-rw-r--r--drivers/isdn/hardware/eicon/di.h118
-rw-r--r--drivers/isdn/hardware/eicon/di_dbg.h37
-rw-r--r--drivers/isdn/hardware/eicon/di_defs.h181
-rw-r--r--drivers/isdn/hardware/eicon/did_vers.h26
-rw-r--r--drivers/isdn/hardware/eicon/diddfunc.c115
-rw-r--r--drivers/isdn/hardware/eicon/diva.c660
-rw-r--r--drivers/isdn/hardware/eicon/diva.h31
-rw-r--r--drivers/isdn/hardware/eicon/diva_didd.c151
-rw-r--r--drivers/isdn/hardware/eicon/diva_dma.c94
-rw-r--r--drivers/isdn/hardware/eicon/diva_dma.h48
-rw-r--r--drivers/isdn/hardware/eicon/diva_pci.h19
-rw-r--r--drivers/isdn/hardware/eicon/divacapi.h1360
-rw-r--r--drivers/isdn/hardware/eicon/divamnt.c257
-rw-r--r--drivers/isdn/hardware/eicon/divasfunc.c238
-rw-r--r--drivers/isdn/hardware/eicon/divasi.c581
-rw-r--r--drivers/isdn/hardware/eicon/divasmain.c856
-rw-r--r--drivers/isdn/hardware/eicon/divasproc.c441
-rw-r--r--drivers/isdn/hardware/eicon/divasync.h490
-rw-r--r--drivers/isdn/hardware/eicon/dqueue.c110
-rw-r--r--drivers/isdn/hardware/eicon/dqueue.h31
-rw-r--r--drivers/isdn/hardware/eicon/dsp_defs.h304
-rw-r--r--drivers/isdn/hardware/eicon/dsp_tst.h47
-rw-r--r--drivers/isdn/hardware/eicon/dspdids.h75
-rw-r--r--drivers/isdn/hardware/eicon/dsrv4bri.h40
-rw-r--r--drivers/isdn/hardware/eicon/dsrv_bri.h37
-rw-r--r--drivers/isdn/hardware/eicon/dsrv_pri.h38
-rw-r--r--drivers/isdn/hardware/eicon/entity.h28
-rw-r--r--drivers/isdn/hardware/eicon/helpers.h51
-rw-r--r--drivers/isdn/hardware/eicon/idifunc.c267
-rw-r--r--drivers/isdn/hardware/eicon/io.c852
-rw-r--r--drivers/isdn/hardware/eicon/io.h308
-rw-r--r--drivers/isdn/hardware/eicon/istream.c226
-rw-r--r--drivers/isdn/hardware/eicon/kst_ifc.h336
-rw-r--r--drivers/isdn/hardware/eicon/main_if.h50
-rw-r--r--drivers/isdn/hardware/eicon/maintidi.c2194
-rw-r--r--drivers/isdn/hardware/eicon/maintidi.h172
-rw-r--r--drivers/isdn/hardware/eicon/man_defs.h133
-rw-r--r--drivers/isdn/hardware/eicon/mdm_msg.h346
-rw-r--r--drivers/isdn/hardware/eicon/message.c15047
-rw-r--r--drivers/isdn/hardware/eicon/mi_pc.h204
-rw-r--r--drivers/isdn/hardware/eicon/mntfunc.c370
-rw-r--r--drivers/isdn/hardware/eicon/os_4bri.c1131
-rw-r--r--drivers/isdn/hardware/eicon/os_4bri.h8
-rw-r--r--drivers/isdn/hardware/eicon/os_bri.c813
-rw-r--r--drivers/isdn/hardware/eicon/os_bri.h8
-rw-r--r--drivers/isdn/hardware/eicon/os_capi.h21
-rw-r--r--drivers/isdn/hardware/eicon/os_pri.c1051
-rw-r--r--drivers/isdn/hardware/eicon/os_pri.h8
-rw-r--r--drivers/isdn/hardware/eicon/pc.h738
-rw-r--r--drivers/isdn/hardware/eicon/pc_init.h267
-rw-r--r--drivers/isdn/hardware/eicon/pc_maint.h160
-rw-r--r--drivers/isdn/hardware/eicon/pkmaint.h44
-rw-r--r--drivers/isdn/hardware/eicon/platform.h394
-rw-r--r--drivers/isdn/hardware/eicon/pr_pc.h76
-rw-r--r--drivers/isdn/hardware/eicon/s_4bri.c510
-rw-r--r--drivers/isdn/hardware/eicon/s_bri.c191
-rw-r--r--drivers/isdn/hardware/eicon/s_pri.c205
-rw-r--r--drivers/isdn/hardware/eicon/sdp_hdr.h117
-rw-r--r--drivers/isdn/hardware/eicon/um_idi.c885
-rw-r--r--drivers/isdn/hardware/eicon/um_idi.h43
-rw-r--r--drivers/isdn/hardware/eicon/um_xdi.h68
-rw-r--r--drivers/isdn/hardware/eicon/xdi_adapter.h70
-rw-r--r--drivers/isdn/hardware/eicon/xdi_msg.h127
-rw-r--r--drivers/isdn/hardware/eicon/xdi_vers.h26
98 files changed, 48238 insertions, 0 deletions
diff --git a/drivers/isdn/hardware/Kconfig b/drivers/isdn/hardware/Kconfig
new file mode 100644
index 000000000000..139f19797713
--- /dev/null
+++ b/drivers/isdn/hardware/Kconfig
@@ -0,0 +1,10 @@
1#
2# ISDN hardware drivers
3#
4comment "CAPI hardware drivers"
5 depends on NET && ISDN && ISDN_CAPI
6
7source "drivers/isdn/hardware/avm/Kconfig"
8
9source "drivers/isdn/hardware/eicon/Kconfig"
10
diff --git a/drivers/isdn/hardware/Makefile b/drivers/isdn/hardware/Makefile
new file mode 100644
index 000000000000..11c8a183948c
--- /dev/null
+++ b/drivers/isdn/hardware/Makefile
@@ -0,0 +1,6 @@
1# Makefile for the CAPI hardware drivers
2
3# Object files in subdirectories
4
5obj-$(CONFIG_CAPI_AVM) += avm/
6obj-$(CONFIG_CAPI_EICON) += eicon/
diff --git a/drivers/isdn/hardware/avm/Kconfig b/drivers/isdn/hardware/avm/Kconfig
new file mode 100644
index 000000000000..29a32a8830c0
--- /dev/null
+++ b/drivers/isdn/hardware/avm/Kconfig
@@ -0,0 +1,66 @@
1#
2# ISDN AVM drivers
3#
4
5menu "Active AVM cards"
6 depends on NET && ISDN && ISDN_CAPI!=n
7
8config CAPI_AVM
9 bool "Support AVM cards"
10 help
11 Enable support for AVM active ISDN cards.
12
13config ISDN_DRV_AVMB1_B1ISA
14 tristate "AVM B1 ISA support"
15 depends on CAPI_AVM && ISDN_CAPI && ISA
16 help
17 Enable support for the ISA version of the AVM B1 card.
18
19config ISDN_DRV_AVMB1_B1PCI
20 tristate "AVM B1 PCI support"
21 depends on CAPI_AVM && ISDN_CAPI && PCI
22 help
23 Enable support for the PCI version of the AVM B1 card.
24
25config ISDN_DRV_AVMB1_B1PCIV4
26 bool "AVM B1 PCI V4 support"
27 depends on ISDN_DRV_AVMB1_B1PCI
28 help
29 Enable support for the V4 version of AVM B1 PCI card.
30
31config ISDN_DRV_AVMB1_T1ISA
32 tristate "AVM T1/T1-B ISA support"
33 depends on CAPI_AVM && ISDN_CAPI && ISA
34 help
35 Enable support for the AVM T1 T1B card.
36 Note: This is a PRI card and handle 30 B-channels.
37
38config ISDN_DRV_AVMB1_B1PCMCIA
39 tristate "AVM B1/M1/M2 PCMCIA support"
40 depends on CAPI_AVM && ISDN_CAPI
41 help
42 Enable support for the PCMCIA version of the AVM B1 card.
43
44config ISDN_DRV_AVMB1_AVM_CS
45 tristate "AVM B1/M1/M2 PCMCIA cs module"
46 depends on ISDN_DRV_AVMB1_B1PCMCIA && PCMCIA
47 help
48 Enable the PCMCIA client driver for the AVM B1/M1/M2
49 PCMCIA cards.
50
51config ISDN_DRV_AVMB1_T1PCI
52 tristate "AVM T1/T1-B PCI support"
53 depends on CAPI_AVM && ISDN_CAPI && PCI
54 help
55 Enable support for the AVM T1 T1B card.
56 Note: This is a PRI card and handle 30 B-channels.
57
58config ISDN_DRV_AVMB1_C4
59 tristate "AVM C4/C2 support"
60 depends on CAPI_AVM && ISDN_CAPI && PCI
61 help
62 Enable support for the AVM C4/C2 PCI cards.
63 These cards handle 4/2 BRI ISDN lines (8/4 channels).
64
65endmenu
66
diff --git a/drivers/isdn/hardware/avm/Makefile b/drivers/isdn/hardware/avm/Makefile
new file mode 100644
index 000000000000..b540e8f2efb6
--- /dev/null
+++ b/drivers/isdn/hardware/avm/Makefile
@@ -0,0 +1,11 @@
1# Makefile for the AVM ISDN device drivers
2
3# Each configuration option enables a list of files.
4
5obj-$(CONFIG_ISDN_DRV_AVMB1_B1ISA) += b1isa.o b1.o
6obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCI) += b1pci.o b1.o b1dma.o
7obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCMCIA) += b1pcmcia.o b1.o
8obj-$(CONFIG_ISDN_DRV_AVMB1_AVM_CS) += avm_cs.o
9obj-$(CONFIG_ISDN_DRV_AVMB1_T1ISA) += t1isa.o b1.o
10obj-$(CONFIG_ISDN_DRV_AVMB1_T1PCI) += t1pci.o b1.o b1dma.o
11obj-$(CONFIG_ISDN_DRV_AVMB1_C4) += c4.o b1.o
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
new file mode 100644
index 000000000000..dc00c85e3e35
--- /dev/null
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -0,0 +1,510 @@
1/* $Id: avm_cs.c,v 1.4.6.3 2001/09/23 22:24:33 kai Exp $
2 *
3 * A PCMCIA client driver for AVM B1/M1/M2
4 *
5 * Copyright 1999 by Carsten Paeth <calle@calle.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/sched.h>
16#include <linux/ptrace.h>
17#include <linux/slab.h>
18#include <linux/string.h>
19#include <linux/tty.h>
20#include <linux/serial.h>
21#include <linux/major.h>
22#include <asm/io.h>
23#include <asm/system.h>
24
25#include <pcmcia/version.h>
26#include <pcmcia/cs_types.h>
27#include <pcmcia/cs.h>
28#include <pcmcia/cistpl.h>
29#include <pcmcia/ciscode.h>
30#include <pcmcia/ds.h>
31#include <pcmcia/cisreg.h>
32
33#include <linux/skbuff.h>
34#include <linux/capi.h>
35#include <linux/b1lli.h>
36#include <linux/b1pcmcia.h>
37
38/*====================================================================*/
39
40MODULE_DESCRIPTION("CAPI4Linux: PCMCIA client driver for AVM B1/M1/M2");
41MODULE_AUTHOR("Carsten Paeth");
42MODULE_LICENSE("GPL");
43
44/*====================================================================*/
45
46/*
47 The event() function is this driver's Card Services event handler.
48 It will be called by Card Services when an appropriate card status
49 event is received. The config() and release() entry points are
50 used to configure or release a socket, in response to card insertion
51 and ejection events. They are invoked from the skeleton event
52 handler.
53*/
54
55static void avmcs_config(dev_link_t *link);
56static void avmcs_release(dev_link_t *link);
57static int avmcs_event(event_t event, int priority,
58 event_callback_args_t *args);
59
60/*
61 The attach() and detach() entry points are used to create and destroy
62 "instances" of the driver, where each instance represents everything
63 needed to manage one actual PCMCIA card.
64*/
65
66static dev_link_t *avmcs_attach(void);
67static void avmcs_detach(dev_link_t *);
68
69/*
70 The dev_info variable is the "key" that is used to match up this
71 device driver with appropriate cards, through the card configuration
72 database.
73*/
74
75static dev_info_t dev_info = "avm_cs";
76
77/*
78 A linked list of "instances" of the skeleton device. Each actual
79 PCMCIA card corresponds to one device instance, and is described
80 by one dev_link_t structure (defined in ds.h).
81
82 You may not want to use a linked list for this -- for example, the
83 memory card driver uses an array of dev_link_t pointers, where minor
84 device numbers are used to derive the corresponding array index.
85*/
86
87static dev_link_t *dev_list = NULL;
88
89/*
90 A dev_link_t structure has fields for most things that are needed
91 to keep track of a socket, but there will usually be some device
92 specific information that also needs to be kept track of. The
93 'priv' pointer in a dev_link_t structure can be used to point to
94 a device-specific private data structure, like this.
95
96 A driver needs to provide a dev_node_t structure for each device
97 on a card. In some cases, there is only one device per card (for
98 example, ethernet cards, modems). In other cases, there may be
99 many actual or logical devices (SCSI adapters, memory cards with
100 multiple partitions). The dev_node_t structures need to be kept
101 in a linked list starting at the 'dev' field of a dev_link_t
102 structure. We allocate them in the card's private data structure,
103 because they generally can't be allocated dynamically.
104*/
105
106typedef struct local_info_t {
107 dev_node_t node;
108} local_info_t;
109
110/*======================================================================
111
112 avmcs_attach() creates an "instance" of the driver, allocating
113 local data structures for one device. The device is registered
114 with Card Services.
115
116 The dev_link structure is initialized, but we don't actually
117 configure the card at this point -- we wait until we receive a
118 card insertion event.
119
120======================================================================*/
121
122static dev_link_t *avmcs_attach(void)
123{
124 client_reg_t client_reg;
125 dev_link_t *link;
126 local_info_t *local;
127 int ret;
128
129 /* Initialize the dev_link_t structure */
130 link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
131 if (!link)
132 goto err;
133 memset(link, 0, sizeof(struct dev_link_t));
134
135 /* The io structure describes IO port mapping */
136 link->io.NumPorts1 = 16;
137 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
138 link->io.NumPorts2 = 0;
139
140 /* Interrupt setup */
141 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
142 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
143
144 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
145
146 /* General socket configuration */
147 link->conf.Attributes = CONF_ENABLE_IRQ;
148 link->conf.Vcc = 50;
149 link->conf.IntType = INT_MEMORY_AND_IO;
150 link->conf.ConfigIndex = 1;
151 link->conf.Present = PRESENT_OPTION;
152
153 /* Allocate space for private device-specific data */
154 local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
155 if (!local)
156 goto err_kfree;
157 memset(local, 0, sizeof(local_info_t));
158 link->priv = local;
159
160 /* Register with Card Services */
161 link->next = dev_list;
162 dev_list = link;
163 client_reg.dev_info = &dev_info;
164 client_reg.EventMask =
165 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
166 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
167 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
168 client_reg.event_handler = &avmcs_event;
169 client_reg.Version = 0x0210;
170 client_reg.event_callback_args.client_data = link;
171 ret = pcmcia_register_client(&link->handle, &client_reg);
172 if (ret != 0) {
173 cs_error(link->handle, RegisterClient, ret);
174 avmcs_detach(link);
175 goto err;
176 }
177 return link;
178
179 err_kfree:
180 kfree(link);
181 err:
182 return NULL;
183} /* avmcs_attach */
184
185/*======================================================================
186
187 This deletes a driver "instance". The device is de-registered
188 with Card Services. If it has been released, all local data
189 structures are freed. Otherwise, the structures will be freed
190 when the device is released.
191
192======================================================================*/
193
194static void avmcs_detach(dev_link_t *link)
195{
196 dev_link_t **linkp;
197
198 /* Locate device structure */
199 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
200 if (*linkp == link) break;
201 if (*linkp == NULL)
202 return;
203
204 /*
205 If the device is currently configured and active, we won't
206 actually delete it yet. Instead, it is marked so that when
207 the release() function is called, that will trigger a proper
208 detach().
209 */
210 if (link->state & DEV_CONFIG) {
211 link->state |= DEV_STALE_LINK;
212 return;
213 }
214
215 /* Break the link with Card Services */
216 if (link->handle)
217 pcmcia_deregister_client(link->handle);
218
219 /* Unlink device structure, free pieces */
220 *linkp = link->next;
221 if (link->priv) {
222 kfree(link->priv);
223 }
224 kfree(link);
225
226} /* avmcs_detach */
227
228/*======================================================================
229
230 avmcs_config() is scheduled to run after a CARD_INSERTION event
231 is received, to configure the PCMCIA socket, and to make the
232 ethernet device available to the system.
233
234======================================================================*/
235
236static int get_tuple(client_handle_t handle, tuple_t *tuple,
237 cisparse_t *parse)
238{
239 int i = pcmcia_get_tuple_data(handle, tuple);
240 if (i != CS_SUCCESS) return i;
241 return pcmcia_parse_tuple(handle, tuple, parse);
242}
243
244static int first_tuple(client_handle_t handle, tuple_t *tuple,
245 cisparse_t *parse)
246{
247 int i = pcmcia_get_first_tuple(handle, tuple);
248 if (i != CS_SUCCESS) return i;
249 return get_tuple(handle, tuple, parse);
250}
251
252static int next_tuple(client_handle_t handle, tuple_t *tuple,
253 cisparse_t *parse)
254{
255 int i = pcmcia_get_next_tuple(handle, tuple);
256 if (i != CS_SUCCESS) return i;
257 return get_tuple(handle, tuple, parse);
258}
259
260static void avmcs_config(dev_link_t *link)
261{
262 client_handle_t handle;
263 tuple_t tuple;
264 cisparse_t parse;
265 cistpl_cftable_entry_t *cf = &parse.cftable_entry;
266 local_info_t *dev;
267 int i;
268 u_char buf[64];
269 char devname[128];
270 int cardtype;
271 int (*addcard)(unsigned int port, unsigned irq);
272
273 handle = link->handle;
274 dev = link->priv;
275
276 /*
277 This reads the card's CONFIG tuple to find its configuration
278 registers.
279 */
280 do {
281 tuple.DesiredTuple = CISTPL_CONFIG;
282 i = pcmcia_get_first_tuple(handle, &tuple);
283 if (i != CS_SUCCESS) break;
284 tuple.TupleData = buf;
285 tuple.TupleDataMax = 64;
286 tuple.TupleOffset = 0;
287 i = pcmcia_get_tuple_data(handle, &tuple);
288 if (i != CS_SUCCESS) break;
289 i = pcmcia_parse_tuple(handle, &tuple, &parse);
290 if (i != CS_SUCCESS) break;
291 link->conf.ConfigBase = parse.config.base;
292 } while (0);
293 if (i != CS_SUCCESS) {
294 cs_error(link->handle, ParseTuple, i);
295 link->state &= ~DEV_CONFIG_PENDING;
296 return;
297 }
298
299 /* Configure card */
300 link->state |= DEV_CONFIG;
301
302 do {
303
304 tuple.Attributes = 0;
305 tuple.TupleData = buf;
306 tuple.TupleDataMax = 254;
307 tuple.TupleOffset = 0;
308 tuple.DesiredTuple = CISTPL_VERS_1;
309
310 devname[0] = 0;
311 if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
312 strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1],
313 sizeof(devname));
314 }
315 /*
316 * find IO port
317 */
318 tuple.TupleData = (cisdata_t *)buf;
319 tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
320 tuple.Attributes = 0;
321 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
322 i = first_tuple(handle, &tuple, &parse);
323 while (i == CS_SUCCESS) {
324 if (cf->io.nwin > 0) {
325 link->conf.ConfigIndex = cf->index;
326 link->io.BasePort1 = cf->io.win[0].base;
327 link->io.NumPorts1 = cf->io.win[0].len;
328 link->io.NumPorts2 = 0;
329 printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
330 link->io.BasePort1,
331 link->io.BasePort1+link->io.NumPorts1-1);
332 i = pcmcia_request_io(link->handle, &link->io);
333 if (i == CS_SUCCESS) goto found_port;
334 }
335 i = next_tuple(handle, &tuple, &parse);
336 }
337
338found_port:
339 if (i != CS_SUCCESS) {
340 cs_error(link->handle, RequestIO, i);
341 break;
342 }
343
344 /*
345 * allocate an interrupt line
346 */
347 i = pcmcia_request_irq(link->handle, &link->irq);
348 if (i != CS_SUCCESS) {
349 cs_error(link->handle, RequestIRQ, i);
350 pcmcia_release_io(link->handle, &link->io);
351 break;
352 }
353
354 /*
355 * configure the PCMCIA socket
356 */
357 i = pcmcia_request_configuration(link->handle, &link->conf);
358 if (i != CS_SUCCESS) {
359 cs_error(link->handle, RequestConfiguration, i);
360 pcmcia_release_io(link->handle, &link->io);
361 pcmcia_release_irq(link->handle, &link->irq);
362 break;
363 }
364
365 } while (0);
366
367 /* At this point, the dev_node_t structure(s) should be
368 initialized and arranged in a linked list at link->dev. */
369
370 if (devname[0]) {
371 char *s = strrchr(devname, ' ');
372 if (!s)
373 s = devname;
374 else s++;
375 strcpy(dev->node.dev_name, s);
376 if (strcmp("M1", s) == 0) {
377 cardtype = AVM_CARDTYPE_M1;
378 } else if (strcmp("M2", s) == 0) {
379 cardtype = AVM_CARDTYPE_M2;
380 } else {
381 cardtype = AVM_CARDTYPE_B1;
382 }
383 } else {
384 strcpy(dev->node.dev_name, "b1");
385 cardtype = AVM_CARDTYPE_B1;
386 }
387
388 dev->node.major = 64;
389 dev->node.minor = 0;
390 link->dev = &dev->node;
391
392 link->state &= ~DEV_CONFIG_PENDING;
393 /* If any step failed, release any partially configured state */
394 if (i != 0) {
395 avmcs_release(link);
396 return;
397 }
398
399
400 switch (cardtype) {
401 case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break;
402 case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break;
403 default:
404 case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break;
405 }
406 if ((i = (*addcard)(link->io.BasePort1, link->irq.AssignedIRQ)) < 0) {
407 printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n",
408 dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ);
409 avmcs_release(link);
410 return;
411 }
412 dev->node.minor = i;
413
414} /* avmcs_config */
415
416/*======================================================================
417
418 After a card is removed, avmcs_release() will unregister the net
419 device, and release the PCMCIA configuration. If the device is
420 still open, this will be postponed until it is closed.
421
422======================================================================*/
423
424static void avmcs_release(dev_link_t *link)
425{
426 b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);
427
428 /* Unlink the device chain */
429 link->dev = NULL;
430
431 /* Don't bother checking to see if these succeed or not */
432 pcmcia_release_configuration(link->handle);
433 pcmcia_release_io(link->handle, &link->io);
434 pcmcia_release_irq(link->handle, &link->irq);
435 link->state &= ~DEV_CONFIG;
436
437 if (link->state & DEV_STALE_LINK)
438 avmcs_detach(link);
439
440} /* avmcs_release */
441
442/*======================================================================
443
444 The card status event handler. Mostly, this schedules other
445 stuff to run after an event is received. A CARD_REMOVAL event
446 also sets some flags to discourage the net drivers from trying
447 to talk to the card any more.
448
449 When a CARD_REMOVAL event is received, we immediately set a flag
450 to block future accesses to this device. All the functions that
451 actually access the device should check this flag to make sure
452 the card is still present.
453
454======================================================================*/
455
456static int avmcs_event(event_t event, int priority,
457 event_callback_args_t *args)
458{
459 dev_link_t *link = args->client_data;
460
461 switch (event) {
462 case CS_EVENT_CARD_REMOVAL:
463 link->state &= ~DEV_PRESENT;
464 if (link->state & DEV_CONFIG)
465 avmcs_release(link);
466 break;
467 case CS_EVENT_CARD_INSERTION:
468 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
469 avmcs_config(link);
470 break;
471 case CS_EVENT_PM_SUSPEND:
472 link->state |= DEV_SUSPEND;
473 /* Fall through... */
474 case CS_EVENT_RESET_PHYSICAL:
475 if (link->state & DEV_CONFIG)
476 pcmcia_release_configuration(link->handle);
477 break;
478 case CS_EVENT_PM_RESUME:
479 link->state &= ~DEV_SUSPEND;
480 /* Fall through... */
481 case CS_EVENT_CARD_RESET:
482 if (link->state & DEV_CONFIG)
483 pcmcia_request_configuration(link->handle, &link->conf);
484 break;
485 }
486 return 0;
487} /* avmcs_event */
488
489static struct pcmcia_driver avmcs_driver = {
490 .owner = THIS_MODULE,
491 .drv = {
492 .name = "avm_cs",
493 },
494 .attach = avmcs_attach,
495 .detach = avmcs_detach,
496};
497
498static int __init avmcs_init(void)
499{
500 return pcmcia_register_driver(&avmcs_driver);
501}
502
503static void __exit avmcs_exit(void)
504{
505 pcmcia_unregister_driver(&avmcs_driver);
506 BUG_ON(dev_list != NULL);
507}
508
509module_init(avmcs_init);
510module_exit(avmcs_exit);
diff --git a/drivers/isdn/hardware/avm/avmcard.h b/drivers/isdn/hardware/avm/avmcard.h
new file mode 100644
index 000000000000..296d6a6f749f
--- /dev/null
+++ b/drivers/isdn/hardware/avm/avmcard.h
@@ -0,0 +1,585 @@
1/* $Id: avmcard.h,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
2 *
3 * Copyright 1999 by Carsten Paeth <calle@calle.de>
4 *
5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference.
7 *
8 */
9
10#ifndef _AVMCARD_H_
11#define _AVMCARD_H_
12
13#include <linux/spinlock.h>
14#include <linux/list.h>
15#include <linux/interrupt.h>
16
17#define AVMB1_PORTLEN 0x1f
18#define AVM_MAXVERSION 8
19#define AVM_NCCI_PER_CHANNEL 4
20
21/*
22 * Versions
23 */
24
25#define VER_DRIVER 0
26#define VER_CARDTYPE 1
27#define VER_HWID 2
28#define VER_SERIAL 3
29#define VER_OPTION 4
30#define VER_PROTO 5
31#define VER_PROFILE 6
32#define VER_CAPI 7
33
34enum avmcardtype {
35 avm_b1isa,
36 avm_b1pci,
37 avm_b1pcmcia,
38 avm_m1,
39 avm_m2,
40 avm_t1isa,
41 avm_t1pci,
42 avm_c4,
43 avm_c2
44};
45
46typedef struct avmcard_dmabuf {
47 long size;
48 u8 *dmabuf;
49 dma_addr_t dmaaddr;
50} avmcard_dmabuf;
51
52typedef struct avmcard_dmainfo {
53 u32 recvlen;
54 avmcard_dmabuf recvbuf;
55
56 avmcard_dmabuf sendbuf;
57 struct sk_buff_head send_queue;
58
59 struct pci_dev *pcidev;
60} avmcard_dmainfo;
61
62typedef struct avmctrl_info {
63 char cardname[32];
64
65 int versionlen;
66 char versionbuf[1024];
67 char *version[AVM_MAXVERSION];
68
69 char infobuf[128]; /* for function procinfo */
70
71 struct avmcard *card;
72 struct capi_ctr capi_ctrl;
73
74 struct list_head ncci_head;
75} avmctrl_info;
76
77typedef struct avmcard {
78 char name[32];
79
80 spinlock_t lock;
81 unsigned int port;
82 unsigned irq;
83 unsigned long membase;
84 enum avmcardtype cardtype;
85 unsigned char revision;
86 unsigned char class;
87 int cardnr; /* for t1isa */
88
89 char msgbuf[128]; /* capimsg msg part */
90 char databuf[2048]; /* capimsg data part */
91
92 void __iomem *mbase;
93 volatile u32 csr;
94 avmcard_dmainfo *dma;
95
96 struct avmctrl_info *ctrlinfo;
97
98 u_int nr_controllers;
99 u_int nlogcontr;
100 struct list_head list;
101} avmcard;
102
103extern int b1_irq_table[16];
104
105/*
106 * LLI Messages to the ISDN-ControllerISDN Controller
107 */
108
109#define SEND_POLL 0x72 /*
110 * after load <- RECEIVE_POLL
111 */
112#define SEND_INIT 0x11 /*
113 * first message <- RECEIVE_INIT
114 * int32 NumApplications int32
115 * NumNCCIs int32 BoardNumber
116 */
117#define SEND_REGISTER 0x12 /*
118 * register an application int32
119 * ApplIDId int32 NumMessages
120 * int32 NumB3Connections int32
121 * NumB3Blocks int32 B3Size
122 *
123 * AnzB3Connection != 0 &&
124 * AnzB3Blocks >= 1 && B3Size >= 1
125 */
126#define SEND_RELEASE 0x14 /*
127 * deregister an application int32
128 * ApplID
129 */
130#define SEND_MESSAGE 0x15 /*
131 * send capi-message int32 length
132 * capi-data ...
133 */
134#define SEND_DATA_B3_REQ 0x13 /*
135 * send capi-data-message int32
136 * MsgLength capi-data ... int32
137 * B3Length data ....
138 */
139
140#define SEND_CONFIG 0x21 /*
141 */
142
143#define SEND_POLLACK 0x73 /* T1 Watchdog */
144
145/*
146 * LLI Messages from the ISDN-ControllerISDN Controller
147 */
148
149#define RECEIVE_POLL 0x32 /*
150 * <- after SEND_POLL
151 */
152#define RECEIVE_INIT 0x27 /*
153 * <- after SEND_INIT int32 length
154 * byte total length b1struct board
155 * driver revision b1struct card
156 * type b1struct reserved b1struct
157 * serial number b1struct driver
158 * capability b1struct d-channel
159 * protocol b1struct CAPI-2.0
160 * profile b1struct capi version
161 */
162#define RECEIVE_MESSAGE 0x21 /*
163 * <- after SEND_MESSAGE int32
164 * AppllID int32 Length capi-data
165 * ....
166 */
167#define RECEIVE_DATA_B3_IND 0x22 /*
168 * received data int32 AppllID
169 * int32 Length capi-data ...
170 * int32 B3Length data ...
171 */
172#define RECEIVE_START 0x23 /*
173 * Handshake
174 */
175#define RECEIVE_STOP 0x24 /*
176 * Handshake
177 */
178#define RECEIVE_NEW_NCCI 0x25 /*
179 * int32 AppllID int32 NCCI int32
180 * WindowSize
181 */
182#define RECEIVE_FREE_NCCI 0x26 /*
183 * int32 AppllID int32 NCCI
184 */
185#define RECEIVE_RELEASE 0x26 /*
186 * int32 AppllID int32 0xffffffff
187 */
188#define RECEIVE_TASK_READY 0x31 /*
189 * int32 tasknr
190 * int32 Length Taskname ...
191 */
192#define RECEIVE_DEBUGMSG 0x71 /*
193 * int32 Length message
194 *
195 */
196#define RECEIVE_POLLDWORD 0x75 /* t1pci in dword mode */
197
198#define WRITE_REGISTER 0x00
199#define READ_REGISTER 0x01
200
201/*
202 * port offsets
203 */
204
205#define B1_READ 0x00
206#define B1_WRITE 0x01
207#define B1_INSTAT 0x02
208#define B1_OUTSTAT 0x03
209#define B1_ANALYSE 0x04
210#define B1_REVISION 0x05
211#define B1_RESET 0x10
212
213
214#define B1_STAT0(cardtype) ((cardtype) == avm_m1 ? 0x81200000l : 0x80A00000l)
215#define B1_STAT1(cardtype) (0x80E00000l)
216
217/* ---------------------------------------------------------------- */
218
219static inline unsigned char b1outp(unsigned int base,
220 unsigned short offset,
221 unsigned char value)
222{
223 outb(value, base + offset);
224 return inb(base + B1_ANALYSE);
225}
226
227
228static inline int b1_rx_full(unsigned int base)
229{
230 return inb(base + B1_INSTAT) & 0x1;
231}
232
233static inline unsigned char b1_get_byte(unsigned int base)
234{
235 unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */
236 while (!b1_rx_full(base) && time_before(jiffies, stop));
237 if (b1_rx_full(base))
238 return inb(base + B1_READ);
239 printk(KERN_CRIT "b1lli(0x%x): rx not full after 1 second\n", base);
240 return 0;
241}
242
243static inline unsigned int b1_get_word(unsigned int base)
244{
245 unsigned int val = 0;
246 val |= b1_get_byte(base);
247 val |= (b1_get_byte(base) << 8);
248 val |= (b1_get_byte(base) << 16);
249 val |= (b1_get_byte(base) << 24);
250 return val;
251}
252
253static inline int b1_tx_empty(unsigned int base)
254{
255 return inb(base + B1_OUTSTAT) & 0x1;
256}
257
258static inline void b1_put_byte(unsigned int base, unsigned char val)
259{
260 while (!b1_tx_empty(base));
261 b1outp(base, B1_WRITE, val);
262}
263
264static inline int b1_save_put_byte(unsigned int base, unsigned char val)
265{
266 unsigned long stop = jiffies + 2 * HZ;
267 while (!b1_tx_empty(base) && time_before(jiffies,stop));
268 if (!b1_tx_empty(base)) return -1;
269 b1outp(base, B1_WRITE, val);
270 return 0;
271}
272
273static inline void b1_put_word(unsigned int base, unsigned int val)
274{
275 b1_put_byte(base, val & 0xff);
276 b1_put_byte(base, (val >> 8) & 0xff);
277 b1_put_byte(base, (val >> 16) & 0xff);
278 b1_put_byte(base, (val >> 24) & 0xff);
279}
280
281static inline unsigned int b1_get_slice(unsigned int base,
282 unsigned char *dp)
283{
284 unsigned int len, i;
285
286 len = i = b1_get_word(base);
287 while (i-- > 0) *dp++ = b1_get_byte(base);
288 return len;
289}
290
291static inline void b1_put_slice(unsigned int base,
292 unsigned char *dp, unsigned int len)
293{
294 unsigned i = len;
295 b1_put_word(base, i);
296 while (i-- > 0)
297 b1_put_byte(base, *dp++);
298}
299
300static void b1_wr_reg(unsigned int base,
301 unsigned int reg,
302 unsigned int value)
303{
304 b1_put_byte(base, WRITE_REGISTER);
305 b1_put_word(base, reg);
306 b1_put_word(base, value);
307}
308
309static inline unsigned int b1_rd_reg(unsigned int base,
310 unsigned int reg)
311{
312 b1_put_byte(base, READ_REGISTER);
313 b1_put_word(base, reg);
314 return b1_get_word(base);
315
316}
317
318static inline void b1_reset(unsigned int base)
319{
320 b1outp(base, B1_RESET, 0);
321 mdelay(55 * 2); /* 2 TIC's */
322
323 b1outp(base, B1_RESET, 1);
324 mdelay(55 * 2); /* 2 TIC's */
325
326 b1outp(base, B1_RESET, 0);
327 mdelay(55 * 2); /* 2 TIC's */
328}
329
330static inline unsigned char b1_disable_irq(unsigned int base)
331{
332 return b1outp(base, B1_INSTAT, 0x00);
333}
334
335/* ---------------------------------------------------------------- */
336
337static inline void b1_set_test_bit(unsigned int base,
338 enum avmcardtype cardtype,
339 int onoff)
340{
341 b1_wr_reg(base, B1_STAT0(cardtype), onoff ? 0x21 : 0x20);
342}
343
344static inline int b1_get_test_bit(unsigned int base,
345 enum avmcardtype cardtype)
346{
347 return (b1_rd_reg(base, B1_STAT0(cardtype)) & 0x01) != 0;
348}
349
350/* ---------------------------------------------------------------- */
351
352#define T1_FASTLINK 0x00
353#define T1_SLOWLINK 0x08
354
355#define T1_READ B1_READ
356#define T1_WRITE B1_WRITE
357#define T1_INSTAT B1_INSTAT
358#define T1_OUTSTAT B1_OUTSTAT
359#define T1_IRQENABLE 0x05
360#define T1_FIFOSTAT 0x06
361#define T1_RESETLINK 0x10
362#define T1_ANALYSE 0x11
363#define T1_IRQMASTER 0x12
364#define T1_IDENT 0x17
365#define T1_RESETBOARD 0x1f
366
367#define T1F_IREADY 0x01
368#define T1F_IHALF 0x02
369#define T1F_IFULL 0x04
370#define T1F_IEMPTY 0x08
371#define T1F_IFLAGS 0xF0
372
373#define T1F_OREADY 0x10
374#define T1F_OHALF 0x20
375#define T1F_OEMPTY 0x40
376#define T1F_OFULL 0x80
377#define T1F_OFLAGS 0xF0
378
379/* there are HEMA cards with 1k and 4k FIFO out */
380#define FIFO_OUTBSIZE 256
381#define FIFO_INPBSIZE 512
382
383#define HEMA_VERSION_ID 0
384#define HEMA_PAL_ID 0
385
386static inline void t1outp(unsigned int base,
387 unsigned short offset,
388 unsigned char value)
389{
390 outb(value, base + offset);
391}
392
393static inline unsigned char t1inp(unsigned int base,
394 unsigned short offset)
395{
396 return inb(base + offset);
397}
398
399static inline int t1_isfastlink(unsigned int base)
400{
401 return (inb(base + T1_IDENT) & ~0x82) == 1;
402}
403
404static inline unsigned char t1_fifostatus(unsigned int base)
405{
406 return inb(base + T1_FIFOSTAT);
407}
408
409static inline unsigned int t1_get_slice(unsigned int base,
410 unsigned char *dp)
411{
412 unsigned int len, i;
413#ifdef FASTLINK_DEBUG
414 unsigned wcnt = 0, bcnt = 0;
415#endif
416
417 len = i = b1_get_word(base);
418 if (t1_isfastlink(base)) {
419 int status;
420 while (i > 0) {
421 status = t1_fifostatus(base) & (T1F_IREADY|T1F_IHALF);
422 if (i >= FIFO_INPBSIZE) status |= T1F_IFULL;
423
424 switch (status) {
425 case T1F_IREADY|T1F_IHALF|T1F_IFULL:
426 insb(base+B1_READ, dp, FIFO_INPBSIZE);
427 dp += FIFO_INPBSIZE;
428 i -= FIFO_INPBSIZE;
429#ifdef FASTLINK_DEBUG
430 wcnt += FIFO_INPBSIZE;
431#endif
432 break;
433 case T1F_IREADY|T1F_IHALF:
434 insb(base+B1_READ,dp, i);
435#ifdef FASTLINK_DEBUG
436 wcnt += i;
437#endif
438 dp += i;
439 i = 0;
440 if (i == 0)
441 break;
442 /* fall through */
443 default:
444 *dp++ = b1_get_byte(base);
445 i--;
446#ifdef FASTLINK_DEBUG
447 bcnt++;
448#endif
449 break;
450 }
451 }
452#ifdef FASTLINK_DEBUG
453 if (wcnt)
454 printk(KERN_DEBUG "b1lli(0x%x): get_slice l=%d w=%d b=%d\n",
455 base, len, wcnt, bcnt);
456#endif
457 } else {
458 while (i-- > 0)
459 *dp++ = b1_get_byte(base);
460 }
461 return len;
462}
463
464static inline void t1_put_slice(unsigned int base,
465 unsigned char *dp, unsigned int len)
466{
467 unsigned i = len;
468 b1_put_word(base, i);
469 if (t1_isfastlink(base)) {
470 int status;
471 while (i > 0) {
472 status = t1_fifostatus(base) & (T1F_OREADY|T1F_OHALF);
473 if (i >= FIFO_OUTBSIZE) status |= T1F_OEMPTY;
474 switch (status) {
475 case T1F_OREADY|T1F_OHALF|T1F_OEMPTY:
476 outsb(base+B1_WRITE, dp, FIFO_OUTBSIZE);
477 dp += FIFO_OUTBSIZE;
478 i -= FIFO_OUTBSIZE;
479 break;
480 case T1F_OREADY|T1F_OHALF:
481 outsb(base+B1_WRITE, dp, i);
482 dp += i;
483 i = 0;
484 break;
485 default:
486 b1_put_byte(base, *dp++);
487 i--;
488 break;
489 }
490 }
491 } else {
492 while (i-- > 0)
493 b1_put_byte(base, *dp++);
494 }
495}
496
497static inline void t1_disable_irq(unsigned int base)
498{
499 t1outp(base, T1_IRQMASTER, 0x00);
500}
501
502static inline void t1_reset(unsigned int base)
503{
504 /* reset T1 Controller */
505 b1_reset(base);
506 /* disable irq on HEMA */
507 t1outp(base, B1_INSTAT, 0x00);
508 t1outp(base, B1_OUTSTAT, 0x00);
509 t1outp(base, T1_IRQMASTER, 0x00);
510 /* reset HEMA board configuration */
511 t1outp(base, T1_RESETBOARD, 0xf);
512}
513
514static inline void b1_setinterrupt(unsigned int base, unsigned irq,
515 enum avmcardtype cardtype)
516{
517 switch (cardtype) {
518 case avm_t1isa:
519 t1outp(base, B1_INSTAT, 0x00);
520 t1outp(base, B1_INSTAT, 0x02);
521 t1outp(base, T1_IRQMASTER, 0x08);
522 break;
523 case avm_b1isa:
524 b1outp(base, B1_INSTAT, 0x00);
525 b1outp(base, B1_RESET, b1_irq_table[irq]);
526 b1outp(base, B1_INSTAT, 0x02);
527 break;
528 default:
529 case avm_m1:
530 case avm_m2:
531 case avm_b1pci:
532 b1outp(base, B1_INSTAT, 0x00);
533 b1outp(base, B1_RESET, 0xf0);
534 b1outp(base, B1_INSTAT, 0x02);
535 break;
536 case avm_c4:
537 case avm_t1pci:
538 b1outp(base, B1_RESET, 0xf0);
539 break;
540 }
541}
542
543/* b1.c */
544avmcard *b1_alloc_card(int nr_controllers);
545void b1_free_card(avmcard *card);
546int b1_detect(unsigned int base, enum avmcardtype cardtype);
547void b1_getrevision(avmcard *card);
548int b1_load_t4file(avmcard *card, capiloaddatapart * t4file);
549int b1_load_config(avmcard *card, capiloaddatapart * config);
550int b1_loaded(avmcard *card);
551
552int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data);
553void b1_reset_ctr(struct capi_ctr *ctrl);
554void b1_register_appl(struct capi_ctr *ctrl, u16 appl,
555 capi_register_params *rp);
556void b1_release_appl(struct capi_ctr *ctrl, u16 appl);
557u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
558void b1_parse_version(avmctrl_info *card);
559irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs);
560
561int b1ctl_read_proc(char *page, char **start, off_t off,
562 int count, int *eof, struct capi_ctr *ctrl);
563
564avmcard_dmainfo *avmcard_dma_alloc(char *name, struct pci_dev *,
565 long rsize, long ssize);
566void avmcard_dma_free(avmcard_dmainfo *);
567
568/* b1dma.c */
569int b1pciv4_detect(avmcard *card);
570int t1pci_detect(avmcard *card);
571void b1dma_reset(avmcard *card);
572irqreturn_t b1dma_interrupt(int interrupt, void *devptr, struct pt_regs *regs);
573
574int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data);
575void b1dma_reset_ctr(struct capi_ctr *ctrl);
576void b1dma_remove_ctr(struct capi_ctr *ctrl);
577void b1dma_register_appl(struct capi_ctr *ctrl,
578 u16 appl,
579 capi_register_params *rp);
580void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl);
581u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
582int b1dmactl_read_proc(char *page, char **start, off_t off,
583 int count, int *eof, struct capi_ctr *ctrl);
584
585#endif /* _AVMCARD_H_ */
diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c
new file mode 100644
index 000000000000..0c7061d55027
--- /dev/null
+++ b/drivers/isdn/hardware/avm/b1.c
@@ -0,0 +1,814 @@
1/* $Id: b1.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
2 *
3 * Common module for AVM B1 cards.
4 *
5 * Copyright 1999 by Carsten Paeth <calle@calle.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/pci.h>
15#include <linux/skbuff.h>
16#include <linux/delay.h>
17#include <linux/mm.h>
18#include <linux/interrupt.h>
19#include <linux/ioport.h>
20#include <linux/capi.h>
21#include <linux/kernelcapi.h>
22#include <asm/io.h>
23#include <linux/init.h>
24#include <asm/uaccess.h>
25#include <linux/netdevice.h>
26#include <linux/isdn/capilli.h>
27#include "avmcard.h"
28#include <linux/isdn/capicmd.h>
29#include <linux/isdn/capiutil.h>
30
31static char *revision = "$Revision: 1.1.2.2 $";
32
33/* ------------------------------------------------------------- */
34
35MODULE_DESCRIPTION("CAPI4Linux: Common support for active AVM cards");
36MODULE_AUTHOR("Carsten Paeth");
37MODULE_LICENSE("GPL");
38
39/* ------------------------------------------------------------- */
40
41int b1_irq_table[16] =
42{0,
43 0,
44 0,
45 192, /* irq 3 */
46 32, /* irq 4 */
47 160, /* irq 5 */
48 96, /* irq 6 */
49 224, /* irq 7 */
50 0,
51 64, /* irq 9 */
52 80, /* irq 10 */
53 208, /* irq 11 */
54 48, /* irq 12 */
55 0,
56 0,
57 112, /* irq 15 */
58};
59
60/* ------------------------------------------------------------- */
61
62avmcard *b1_alloc_card(int nr_controllers)
63{
64 avmcard *card;
65 avmctrl_info *cinfo;
66 int i;
67
68 card = kmalloc(sizeof(*card), GFP_KERNEL);
69 if (!card)
70 return NULL;
71
72 memset(card, 0, sizeof(*card));
73
74 cinfo = kmalloc(sizeof(*cinfo) * nr_controllers, GFP_KERNEL);
75 if (!cinfo) {
76 kfree(card);
77 return NULL;
78 }
79 memset(cinfo, 0, sizeof(*cinfo) * nr_controllers);
80
81 card->ctrlinfo = cinfo;
82 for (i = 0; i < nr_controllers; i++) {
83 INIT_LIST_HEAD(&cinfo[i].ncci_head);
84 cinfo[i].card = card;
85 }
86 spin_lock_init(&card->lock);
87 card->nr_controllers = nr_controllers;
88
89 return card;
90}
91
92/* ------------------------------------------------------------- */
93
94void b1_free_card(avmcard *card)
95{
96 kfree(card->ctrlinfo);
97 kfree(card);
98}
99
100/* ------------------------------------------------------------- */
101
102int b1_detect(unsigned int base, enum avmcardtype cardtype)
103{
104 int onoff, i;
105
106 /*
107 * Statusregister 0000 00xx
108 */
109 if ((inb(base + B1_INSTAT) & 0xfc)
110 || (inb(base + B1_OUTSTAT) & 0xfc))
111 return 1;
112 /*
113 * Statusregister 0000 001x
114 */
115 b1outp(base, B1_INSTAT, 0x2); /* enable irq */
116 /* b1outp(base, B1_OUTSTAT, 0x2); */
117 if ((inb(base + B1_INSTAT) & 0xfe) != 0x2
118 /* || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2 */)
119 return 2;
120 /*
121 * Statusregister 0000 000x
122 */
123 b1outp(base, B1_INSTAT, 0x0); /* disable irq */
124 b1outp(base, B1_OUTSTAT, 0x0);
125 if ((inb(base + B1_INSTAT) & 0xfe)
126 || (inb(base + B1_OUTSTAT) & 0xfe))
127 return 3;
128
129 for (onoff = !0, i= 0; i < 10 ; i++) {
130 b1_set_test_bit(base, cardtype, onoff);
131 if (b1_get_test_bit(base, cardtype) != onoff)
132 return 4;
133 onoff = !onoff;
134 }
135
136 if (cardtype == avm_m1)
137 return 0;
138
139 if ((b1_rd_reg(base, B1_STAT1(cardtype)) & 0x0f) != 0x01)
140 return 5;
141
142 return 0;
143}
144
145void b1_getrevision(avmcard *card)
146{
147 card->class = inb(card->port + B1_ANALYSE);
148 card->revision = inb(card->port + B1_REVISION);
149}
150
151#define FWBUF_SIZE 256
152int b1_load_t4file(avmcard *card, capiloaddatapart * t4file)
153{
154 unsigned char buf[FWBUF_SIZE];
155 unsigned char *dp;
156 int i, left;
157 unsigned int base = card->port;
158
159 dp = t4file->data;
160 left = t4file->len;
161 while (left > FWBUF_SIZE) {
162 if (t4file->user) {
163 if (copy_from_user(buf, dp, FWBUF_SIZE))
164 return -EFAULT;
165 } else {
166 memcpy(buf, dp, FWBUF_SIZE);
167 }
168 for (i = 0; i < FWBUF_SIZE; i++)
169 if (b1_save_put_byte(base, buf[i]) < 0) {
170 printk(KERN_ERR "%s: corrupted firmware file ?\n",
171 card->name);
172 return -EIO;
173 }
174 left -= FWBUF_SIZE;
175 dp += FWBUF_SIZE;
176 }
177 if (left) {
178 if (t4file->user) {
179 if (copy_from_user(buf, dp, left))
180 return -EFAULT;
181 } else {
182 memcpy(buf, dp, left);
183 }
184 for (i = 0; i < left; i++)
185 if (b1_save_put_byte(base, buf[i]) < 0) {
186 printk(KERN_ERR "%s: corrupted firmware file ?\n",
187 card->name);
188 return -EIO;
189 }
190 }
191 return 0;
192}
193
194int b1_load_config(avmcard *card, capiloaddatapart * config)
195{
196 unsigned char buf[FWBUF_SIZE];
197 unsigned char *dp;
198 unsigned int base = card->port;
199 int i, j, left;
200
201 dp = config->data;
202 left = config->len;
203 if (left) {
204 b1_put_byte(base, SEND_CONFIG);
205 b1_put_word(base, 1);
206 b1_put_byte(base, SEND_CONFIG);
207 b1_put_word(base, left);
208 }
209 while (left > FWBUF_SIZE) {
210 if (config->user) {
211 if (copy_from_user(buf, dp, FWBUF_SIZE))
212 return -EFAULT;
213 } else {
214 memcpy(buf, dp, FWBUF_SIZE);
215 }
216 for (i = 0; i < FWBUF_SIZE; ) {
217 b1_put_byte(base, SEND_CONFIG);
218 for (j=0; j < 4; j++) {
219 b1_put_byte(base, buf[i++]);
220 }
221 }
222 left -= FWBUF_SIZE;
223 dp += FWBUF_SIZE;
224 }
225 if (left) {
226 if (config->user) {
227 if (copy_from_user(buf, dp, left))
228 return -EFAULT;
229 } else {
230 memcpy(buf, dp, left);
231 }
232 for (i = 0; i < left; ) {
233 b1_put_byte(base, SEND_CONFIG);
234 for (j=0; j < 4; j++) {
235 if (i < left)
236 b1_put_byte(base, buf[i++]);
237 else
238 b1_put_byte(base, 0);
239 }
240 }
241 }
242 return 0;
243}
244
245int b1_loaded(avmcard *card)
246{
247 unsigned int base = card->port;
248 unsigned long stop;
249 unsigned char ans;
250 unsigned long tout = 2;
251
252 for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
253 if (b1_tx_empty(base))
254 break;
255 }
256 if (!b1_tx_empty(base)) {
257 printk(KERN_ERR "%s: b1_loaded: tx err, corrupted t4 file ?\n",
258 card->name);
259 return 0;
260 }
261 b1_put_byte(base, SEND_POLL);
262 for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
263 if (b1_rx_full(base)) {
264 if ((ans = b1_get_byte(base)) == RECEIVE_POLL) {
265 return 1;
266 }
267 printk(KERN_ERR "%s: b1_loaded: got 0x%x, firmware not running\n",
268 card->name, ans);
269 return 0;
270 }
271 }
272 printk(KERN_ERR "%s: b1_loaded: firmware not running\n", card->name);
273 return 0;
274}
275
276/* ------------------------------------------------------------- */
277
278int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
279{
280 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
281 avmcard *card = cinfo->card;
282 unsigned int port = card->port;
283 unsigned long flags;
284 int retval;
285
286 b1_reset(port);
287
288 if ((retval = b1_load_t4file(card, &data->firmware))) {
289 b1_reset(port);
290 printk(KERN_ERR "%s: failed to load t4file!!\n",
291 card->name);
292 return retval;
293 }
294
295 b1_disable_irq(port);
296
297 if (data->configuration.len > 0 && data->configuration.data) {
298 if ((retval = b1_load_config(card, &data->configuration))) {
299 b1_reset(port);
300 printk(KERN_ERR "%s: failed to load config!!\n",
301 card->name);
302 return retval;
303 }
304 }
305
306 if (!b1_loaded(card)) {
307 printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
308 return -EIO;
309 }
310
311 spin_lock_irqsave(&card->lock, flags);
312 b1_setinterrupt(port, card->irq, card->cardtype);
313 b1_put_byte(port, SEND_INIT);
314 b1_put_word(port, CAPI_MAXAPPL);
315 b1_put_word(port, AVM_NCCI_PER_CHANNEL*2);
316 b1_put_word(port, ctrl->cnr - 1);
317 spin_unlock_irqrestore(&card->lock, flags);
318
319 return 0;
320}
321
322void b1_reset_ctr(struct capi_ctr *ctrl)
323{
324 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
325 avmcard *card = cinfo->card;
326 unsigned int port = card->port;
327
328 b1_reset(port);
329 b1_reset(port);
330
331 memset(cinfo->version, 0, sizeof(cinfo->version));
332 capilib_release(&cinfo->ncci_head);
333 capi_ctr_reseted(ctrl);
334}
335
336void b1_register_appl(struct capi_ctr *ctrl,
337 u16 appl,
338 capi_register_params *rp)
339{
340 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
341 avmcard *card = cinfo->card;
342 unsigned int port = card->port;
343 unsigned long flags;
344 int nconn, want = rp->level3cnt;
345
346 if (want > 0) nconn = want;
347 else nconn = ctrl->profile.nbchannel * -want;
348 if (nconn == 0) nconn = ctrl->profile.nbchannel;
349
350 spin_lock_irqsave(&card->lock, flags);
351 b1_put_byte(port, SEND_REGISTER);
352 b1_put_word(port, appl);
353 b1_put_word(port, 1024 * (nconn+1));
354 b1_put_word(port, nconn);
355 b1_put_word(port, rp->datablkcnt);
356 b1_put_word(port, rp->datablklen);
357 spin_unlock_irqrestore(&card->lock, flags);
358}
359
360void b1_release_appl(struct capi_ctr *ctrl, u16 appl)
361{
362 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
363 avmcard *card = cinfo->card;
364 unsigned int port = card->port;
365 unsigned long flags;
366
367 capilib_release_appl(&cinfo->ncci_head, appl);
368
369 spin_lock_irqsave(&card->lock, flags);
370 b1_put_byte(port, SEND_RELEASE);
371 b1_put_word(port, appl);
372 spin_unlock_irqrestore(&card->lock, flags);
373}
374
375u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
376{
377 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
378 avmcard *card = cinfo->card;
379 unsigned int port = card->port;
380 unsigned long flags;
381 u16 len = CAPIMSG_LEN(skb->data);
382 u8 cmd = CAPIMSG_COMMAND(skb->data);
383 u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
384 u16 dlen, retval;
385
386 if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
387 retval = capilib_data_b3_req(&cinfo->ncci_head,
388 CAPIMSG_APPID(skb->data),
389 CAPIMSG_NCCI(skb->data),
390 CAPIMSG_MSGID(skb->data));
391 if (retval != CAPI_NOERROR)
392 return retval;
393
394 dlen = CAPIMSG_DATALEN(skb->data);
395
396 spin_lock_irqsave(&card->lock, flags);
397 b1_put_byte(port, SEND_DATA_B3_REQ);
398 b1_put_slice(port, skb->data, len);
399 b1_put_slice(port, skb->data + len, dlen);
400 spin_unlock_irqrestore(&card->lock, flags);
401 } else {
402 spin_lock_irqsave(&card->lock, flags);
403 b1_put_byte(port, SEND_MESSAGE);
404 b1_put_slice(port, skb->data, len);
405 spin_unlock_irqrestore(&card->lock, flags);
406 }
407
408 dev_kfree_skb_any(skb);
409 return CAPI_NOERROR;
410}
411
412/* ------------------------------------------------------------- */
413
414void b1_parse_version(avmctrl_info *cinfo)
415{
416 struct capi_ctr *ctrl = &cinfo->capi_ctrl;
417 avmcard *card = cinfo->card;
418 capi_profile *profp;
419 u8 *dversion;
420 u8 flag;
421 int i, j;
422
423 for (j = 0; j < AVM_MAXVERSION; j++)
424 cinfo->version[j] = "\0\0" + 1;
425 for (i = 0, j = 0;
426 j < AVM_MAXVERSION && i < cinfo->versionlen;
427 j++, i += cinfo->versionbuf[i] + 1)
428 cinfo->version[j] = &cinfo->versionbuf[i + 1];
429
430 strlcpy(ctrl->serial, cinfo->version[VER_SERIAL], sizeof(ctrl->serial));
431 memcpy(&ctrl->profile, cinfo->version[VER_PROFILE],sizeof(capi_profile));
432 strlcpy(ctrl->manu, "AVM GmbH", sizeof(ctrl->manu));
433 dversion = cinfo->version[VER_DRIVER];
434 ctrl->version.majorversion = 2;
435 ctrl->version.minorversion = 0;
436 ctrl->version.majormanuversion = (((dversion[0] - '0') & 0xf) << 4);
437 ctrl->version.majormanuversion |= ((dversion[2] - '0') & 0xf);
438 ctrl->version.minormanuversion = (dversion[3] - '0') << 4;
439 ctrl->version.minormanuversion |=
440 (dversion[5] - '0') * 10 + ((dversion[6] - '0') & 0xf);
441
442 profp = &ctrl->profile;
443
444 flag = ((u8 *)(profp->manu))[1];
445 switch (flag) {
446 case 0: if (cinfo->version[VER_CARDTYPE])
447 strcpy(cinfo->cardname, cinfo->version[VER_CARDTYPE]);
448 else strcpy(cinfo->cardname, "B1");
449 break;
450 case 3: strcpy(cinfo->cardname,"PCMCIA B"); break;
451 case 4: strcpy(cinfo->cardname,"PCMCIA M1"); break;
452 case 5: strcpy(cinfo->cardname,"PCMCIA M2"); break;
453 case 6: strcpy(cinfo->cardname,"B1 V3.0"); break;
454 case 7: strcpy(cinfo->cardname,"B1 PCI"); break;
455 default: sprintf(cinfo->cardname, "AVM?%u", (unsigned int)flag); break;
456 }
457 printk(KERN_NOTICE "%s: card %d \"%s\" ready.\n",
458 card->name, ctrl->cnr, cinfo->cardname);
459
460 flag = ((u8 *)(profp->manu))[3];
461 if (flag)
462 printk(KERN_NOTICE "%s: card %d Protocol:%s%s%s%s%s%s%s\n",
463 card->name,
464 ctrl->cnr,
465 (flag & 0x01) ? " DSS1" : "",
466 (flag & 0x02) ? " CT1" : "",
467 (flag & 0x04) ? " VN3" : "",
468 (flag & 0x08) ? " NI1" : "",
469 (flag & 0x10) ? " AUSTEL" : "",
470 (flag & 0x20) ? " ESS" : "",
471 (flag & 0x40) ? " 1TR6" : ""
472 );
473
474 flag = ((u8 *)(profp->manu))[5];
475 if (flag)
476 printk(KERN_NOTICE "%s: card %d Linetype:%s%s%s%s\n",
477 card->name,
478 ctrl->cnr,
479 (flag & 0x01) ? " point to point" : "",
480 (flag & 0x02) ? " point to multipoint" : "",
481 (flag & 0x08) ? " leased line without D-channel" : "",
482 (flag & 0x04) ? " leased line with D-channel" : ""
483 );
484}
485
486/* ------------------------------------------------------------- */
487
488irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
489{
490 avmcard *card = devptr;
491 avmctrl_info *cinfo = &card->ctrlinfo[0];
492 struct capi_ctr *ctrl = &cinfo->capi_ctrl;
493 unsigned char b1cmd;
494 struct sk_buff *skb;
495
496 unsigned ApplId;
497 unsigned MsgLen;
498 unsigned DataB3Len;
499 unsigned NCCI;
500 unsigned WindowSize;
501 unsigned long flags;
502
503 spin_lock_irqsave(&card->lock, flags);
504
505 if (!b1_rx_full(card->port)) {
506 spin_unlock_irqrestore(&card->lock, flags);
507 return IRQ_NONE;
508 }
509
510 b1cmd = b1_get_byte(card->port);
511
512 switch (b1cmd) {
513
514 case RECEIVE_DATA_B3_IND:
515
516 ApplId = (unsigned) b1_get_word(card->port);
517 MsgLen = b1_get_slice(card->port, card->msgbuf);
518 DataB3Len = b1_get_slice(card->port, card->databuf);
519 spin_unlock_irqrestore(&card->lock, flags);
520
521 if (MsgLen < 30) { /* not CAPI 64Bit */
522 memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
523 MsgLen = 30;
524 CAPIMSG_SETLEN(card->msgbuf, 30);
525 }
526 if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) {
527 printk(KERN_ERR "%s: incoming packet dropped\n",
528 card->name);
529 } else {
530 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
531 memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
532 capi_ctr_handle_message(ctrl, ApplId, skb);
533 }
534 break;
535
536 case RECEIVE_MESSAGE:
537
538 ApplId = (unsigned) b1_get_word(card->port);
539 MsgLen = b1_get_slice(card->port, card->msgbuf);
540 spin_unlock_irqrestore(&card->lock, flags);
541 if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
542 printk(KERN_ERR "%s: incoming packet dropped\n",
543 card->name);
544 } else {
545 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
546 if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF)
547 capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
548 CAPIMSG_NCCI(skb->data),
549 CAPIMSG_MSGID(skb->data));
550
551 capi_ctr_handle_message(ctrl, ApplId, skb);
552 }
553 break;
554
555 case RECEIVE_NEW_NCCI:
556
557 ApplId = b1_get_word(card->port);
558 NCCI = b1_get_word(card->port);
559 WindowSize = b1_get_word(card->port);
560 spin_unlock_irqrestore(&card->lock, flags);
561
562 capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
563
564 break;
565
566 case RECEIVE_FREE_NCCI:
567
568 ApplId = b1_get_word(card->port);
569 NCCI = b1_get_word(card->port);
570 spin_unlock_irqrestore(&card->lock, flags);
571
572 if (NCCI != 0xffffffff)
573 capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
574
575 break;
576
577 case RECEIVE_START:
578 /* b1_put_byte(card->port, SEND_POLLACK); */
579 spin_unlock_irqrestore(&card->lock, flags);
580 capi_ctr_resume_output(ctrl);
581 break;
582
583 case RECEIVE_STOP:
584 spin_unlock_irqrestore(&card->lock, flags);
585 capi_ctr_suspend_output(ctrl);
586 break;
587
588 case RECEIVE_INIT:
589
590 cinfo->versionlen = b1_get_slice(card->port, cinfo->versionbuf);
591 spin_unlock_irqrestore(&card->lock, flags);
592 b1_parse_version(cinfo);
593 printk(KERN_INFO "%s: %s-card (%s) now active\n",
594 card->name,
595 cinfo->version[VER_CARDTYPE],
596 cinfo->version[VER_DRIVER]);
597 capi_ctr_ready(ctrl);
598 break;
599
600 case RECEIVE_TASK_READY:
601 ApplId = (unsigned) b1_get_word(card->port);
602 MsgLen = b1_get_slice(card->port, card->msgbuf);
603 spin_unlock_irqrestore(&card->lock, flags);
604 card->msgbuf[MsgLen] = 0;
605 while ( MsgLen > 0
606 && ( card->msgbuf[MsgLen-1] == '\n'
607 || card->msgbuf[MsgLen-1] == '\r')) {
608 card->msgbuf[MsgLen-1] = 0;
609 MsgLen--;
610 }
611 printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
612 card->name, ApplId, card->msgbuf);
613 break;
614
615 case RECEIVE_DEBUGMSG:
616 MsgLen = b1_get_slice(card->port, card->msgbuf);
617 spin_unlock_irqrestore(&card->lock, flags);
618 card->msgbuf[MsgLen] = 0;
619 while ( MsgLen > 0
620 && ( card->msgbuf[MsgLen-1] == '\n'
621 || card->msgbuf[MsgLen-1] == '\r')) {
622 card->msgbuf[MsgLen-1] = 0;
623 MsgLen--;
624 }
625 printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
626 break;
627
628 case 0xff:
629 spin_unlock_irqrestore(&card->lock, flags);
630 printk(KERN_ERR "%s: card removed ?\n", card->name);
631 return IRQ_NONE;
632 default:
633 spin_unlock_irqrestore(&card->lock, flags);
634 printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n",
635 card->name, b1cmd);
636 return IRQ_HANDLED;
637 }
638 return IRQ_HANDLED;
639}
640
641/* ------------------------------------------------------------- */
642int b1ctl_read_proc(char *page, char **start, off_t off,
643 int count, int *eof, struct capi_ctr *ctrl)
644{
645 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
646 avmcard *card = cinfo->card;
647 u8 flag;
648 int len = 0;
649 char *s;
650
651 len += sprintf(page+len, "%-16s %s\n", "name", card->name);
652 len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
653 len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
654 switch (card->cardtype) {
655 case avm_b1isa: s = "B1 ISA"; break;
656 case avm_b1pci: s = "B1 PCI"; break;
657 case avm_b1pcmcia: s = "B1 PCMCIA"; break;
658 case avm_m1: s = "M1"; break;
659 case avm_m2: s = "M2"; break;
660 case avm_t1isa: s = "T1 ISA (HEMA)"; break;
661 case avm_t1pci: s = "T1 PCI"; break;
662 case avm_c4: s = "C4"; break;
663 case avm_c2: s = "C2"; break;
664 default: s = "???"; break;
665 }
666 len += sprintf(page+len, "%-16s %s\n", "type", s);
667 if (card->cardtype == avm_t1isa)
668 len += sprintf(page+len, "%-16s %d\n", "cardnr", card->cardnr);
669 if ((s = cinfo->version[VER_DRIVER]) != 0)
670 len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
671 if ((s = cinfo->version[VER_CARDTYPE]) != 0)
672 len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
673 if ((s = cinfo->version[VER_SERIAL]) != 0)
674 len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
675
676 if (card->cardtype != avm_m1) {
677 flag = ((u8 *)(ctrl->profile.manu))[3];
678 if (flag)
679 len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n",
680 "protocol",
681 (flag & 0x01) ? " DSS1" : "",
682 (flag & 0x02) ? " CT1" : "",
683 (flag & 0x04) ? " VN3" : "",
684 (flag & 0x08) ? " NI1" : "",
685 (flag & 0x10) ? " AUSTEL" : "",
686 (flag & 0x20) ? " ESS" : "",
687 (flag & 0x40) ? " 1TR6" : ""
688 );
689 }
690 if (card->cardtype != avm_m1) {
691 flag = ((u8 *)(ctrl->profile.manu))[5];
692 if (flag)
693 len += sprintf(page+len, "%-16s%s%s%s%s\n",
694 "linetype",
695 (flag & 0x01) ? " point to point" : "",
696 (flag & 0x02) ? " point to multipoint" : "",
697 (flag & 0x08) ? " leased line without D-channel" : "",
698 (flag & 0x04) ? " leased line with D-channel" : ""
699 );
700 }
701 len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
702
703 if (off+count >= len)
704 *eof = 1;
705 if (len < off)
706 return 0;
707 *start = page + off;
708 return ((count < len-off) ? count : len-off);
709}
710
711/* ------------------------------------------------------------- */
712
713#ifdef CONFIG_PCI
714
715avmcard_dmainfo *
716avmcard_dma_alloc(char *name, struct pci_dev *pdev, long rsize, long ssize)
717{
718 avmcard_dmainfo *p;
719 void *buf;
720
721 p = kmalloc(sizeof(avmcard_dmainfo), GFP_KERNEL);
722 if (!p) {
723 printk(KERN_WARNING "%s: no memory.\n", name);
724 goto err;
725 }
726 memset(p, 0, sizeof(avmcard_dmainfo));
727
728 p->recvbuf.size = rsize;
729 buf = pci_alloc_consistent(pdev, rsize, &p->recvbuf.dmaaddr);
730 if (!buf) {
731 printk(KERN_WARNING "%s: allocation of receive dma buffer failed.\n", name);
732 goto err_kfree;
733 }
734 p->recvbuf.dmabuf = buf;
735
736 p->sendbuf.size = ssize;
737 buf = pci_alloc_consistent(pdev, ssize, &p->sendbuf.dmaaddr);
738 if (!buf) {
739 printk(KERN_WARNING "%s: allocation of send dma buffer failed.\n", name);
740 goto err_free_consistent;
741 }
742
743 p->sendbuf.dmabuf = buf;
744 skb_queue_head_init(&p->send_queue);
745
746 return p;
747
748 err_free_consistent:
749 pci_free_consistent(p->pcidev, p->recvbuf.size,
750 p->recvbuf.dmabuf, p->recvbuf.dmaaddr);
751 err_kfree:
752 kfree(p);
753 err:
754 return NULL;
755}
756
757void avmcard_dma_free(avmcard_dmainfo *p)
758{
759 pci_free_consistent(p->pcidev, p->recvbuf.size,
760 p->recvbuf.dmabuf, p->recvbuf.dmaaddr);
761 pci_free_consistent(p->pcidev, p->sendbuf.size,
762 p->sendbuf.dmabuf, p->sendbuf.dmaaddr);
763 skb_queue_purge(&p->send_queue);
764 kfree(p);
765}
766
767EXPORT_SYMBOL(avmcard_dma_alloc);
768EXPORT_SYMBOL(avmcard_dma_free);
769
770#endif
771
772EXPORT_SYMBOL(b1_irq_table);
773
774EXPORT_SYMBOL(b1_alloc_card);
775EXPORT_SYMBOL(b1_free_card);
776EXPORT_SYMBOL(b1_detect);
777EXPORT_SYMBOL(b1_getrevision);
778EXPORT_SYMBOL(b1_load_t4file);
779EXPORT_SYMBOL(b1_load_config);
780EXPORT_SYMBOL(b1_loaded);
781EXPORT_SYMBOL(b1_load_firmware);
782EXPORT_SYMBOL(b1_reset_ctr);
783EXPORT_SYMBOL(b1_register_appl);
784EXPORT_SYMBOL(b1_release_appl);
785EXPORT_SYMBOL(b1_send_message);
786
787EXPORT_SYMBOL(b1_parse_version);
788EXPORT_SYMBOL(b1_interrupt);
789
790EXPORT_SYMBOL(b1ctl_read_proc);
791
792static int __init b1_init(void)
793{
794 char *p;
795 char rev[32];
796
797 if ((p = strchr(revision, ':')) != 0 && p[1]) {
798 strlcpy(rev, p + 2, 32);
799 if ((p = strchr(rev, '$')) != 0 && p > rev)
800 *(p-1) = 0;
801 } else
802 strcpy(rev, "1.0");
803
804 printk(KERN_INFO "b1: revision %s\n", rev);
805
806 return 0;
807}
808
809static void __exit b1_exit(void)
810{
811}
812
813module_init(b1_init);
814module_exit(b1_exit);
diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c
new file mode 100644
index 000000000000..55bed00ca865
--- /dev/null
+++ b/drivers/isdn/hardware/avm/b1dma.c
@@ -0,0 +1,980 @@
1/* $Id: b1dma.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $
2 *
3 * Common module for AVM B1 cards that support dma with AMCC
4 *
5 * Copyright 2000 by Carsten Paeth <calle@calle.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/config.h>
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/skbuff.h>
16#include <linux/delay.h>
17#include <linux/mm.h>
18#include <linux/interrupt.h>
19#include <linux/ioport.h>
20#include <linux/capi.h>
21#include <linux/kernelcapi.h>
22#include <asm/io.h>
23#include <linux/init.h>
24#include <asm/uaccess.h>
25#include <linux/netdevice.h>
26#include <linux/isdn/capilli.h>
27#include "avmcard.h"
28#include <linux/isdn/capicmd.h>
29#include <linux/isdn/capiutil.h>
30
31static char *revision = "$Revision: 1.1.2.3 $";
32
33#undef CONFIG_B1DMA_DEBUG
34
35/* ------------------------------------------------------------- */
36
37MODULE_DESCRIPTION("CAPI4Linux: DMA support for active AVM cards");
38MODULE_AUTHOR("Carsten Paeth");
39MODULE_LICENSE("GPL");
40
41static int suppress_pollack = 0;
42MODULE_PARM(suppress_pollack, "0-1i");
43
44/* ------------------------------------------------------------- */
45
46static void b1dma_dispatch_tx(avmcard *card);
47
48/* ------------------------------------------------------------- */
49
50/* S5933 */
51
52#define AMCC_RXPTR 0x24
53#define AMCC_RXLEN 0x28
54#define AMCC_TXPTR 0x2c
55#define AMCC_TXLEN 0x30
56
57#define AMCC_INTCSR 0x38
58# define EN_READ_TC_INT 0x00008000L
59# define EN_WRITE_TC_INT 0x00004000L
60# define EN_TX_TC_INT EN_READ_TC_INT
61# define EN_RX_TC_INT EN_WRITE_TC_INT
62# define AVM_FLAG 0x30000000L
63
64# define ANY_S5933_INT 0x00800000L
65# define READ_TC_INT 0x00080000L
66# define WRITE_TC_INT 0x00040000L
67# define TX_TC_INT READ_TC_INT
68# define RX_TC_INT WRITE_TC_INT
69# define MASTER_ABORT_INT 0x00100000L
70# define TARGET_ABORT_INT 0x00200000L
71# define BUS_MASTER_INT 0x00200000L
72# define ALL_INT 0x000C0000L
73
74#define AMCC_MCSR 0x3c
75# define A2P_HI_PRIORITY 0x00000100L
76# define EN_A2P_TRANSFERS 0x00000400L
77# define P2A_HI_PRIORITY 0x00001000L
78# define EN_P2A_TRANSFERS 0x00004000L
79# define RESET_A2P_FLAGS 0x04000000L
80# define RESET_P2A_FLAGS 0x02000000L
81
82/* ------------------------------------------------------------- */
83
84static inline void b1dma_writel(avmcard *card, u32 value, int off)
85{
86 writel(value, card->mbase + off);
87}
88
89static inline u32 b1dma_readl(avmcard *card, int off)
90{
91 return readl(card->mbase + off);
92}
93
94/* ------------------------------------------------------------- */
95
96static inline int b1dma_tx_empty(unsigned int port)
97{
98 return inb(port + 0x03) & 0x1;
99}
100
101static inline int b1dma_rx_full(unsigned int port)
102{
103 return inb(port + 0x02) & 0x1;
104}
105
106static int b1dma_tolink(avmcard *card, void *buf, unsigned int len)
107{
108 unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */
109 unsigned char *s = (unsigned char *)buf;
110 while (len--) {
111 while ( !b1dma_tx_empty(card->port)
112 && time_before(jiffies, stop));
113 if (!b1dma_tx_empty(card->port))
114 return -1;
115 t1outp(card->port, 0x01, *s++);
116 }
117 return 0;
118}
119
120static int b1dma_fromlink(avmcard *card, void *buf, unsigned int len)
121{
122 unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */
123 unsigned char *s = (unsigned char *)buf;
124 while (len--) {
125 while ( !b1dma_rx_full(card->port)
126 && time_before(jiffies, stop));
127 if (!b1dma_rx_full(card->port))
128 return -1;
129 *s++ = t1inp(card->port, 0x00);
130 }
131 return 0;
132}
133
134static int WriteReg(avmcard *card, u32 reg, u8 val)
135{
136 u8 cmd = 0x00;
137 if ( b1dma_tolink(card, &cmd, 1) == 0
138 && b1dma_tolink(card, &reg, 4) == 0) {
139 u32 tmp = val;
140 return b1dma_tolink(card, &tmp, 4);
141 }
142 return -1;
143}
144
145static u8 ReadReg(avmcard *card, u32 reg)
146{
147 u8 cmd = 0x01;
148 if ( b1dma_tolink(card, &cmd, 1) == 0
149 && b1dma_tolink(card, &reg, 4) == 0) {
150 u32 tmp;
151 if (b1dma_fromlink(card, &tmp, 4) == 0)
152 return (u8)tmp;
153 }
154 return 0xff;
155}
156
157/* ------------------------------------------------------------- */
158
159static inline void _put_byte(void **pp, u8 val)
160{
161 u8 *s = *pp;
162 *s++ = val;
163 *pp = s;
164}
165
166static inline void _put_word(void **pp, u32 val)
167{
168 u8 *s = *pp;
169 *s++ = val & 0xff;
170 *s++ = (val >> 8) & 0xff;
171 *s++ = (val >> 16) & 0xff;
172 *s++ = (val >> 24) & 0xff;
173 *pp = s;
174}
175
176static inline void _put_slice(void **pp, unsigned char *dp, unsigned int len)
177{
178 unsigned i = len;
179 _put_word(pp, i);
180 while (i-- > 0)
181 _put_byte(pp, *dp++);
182}
183
184static inline u8 _get_byte(void **pp)
185{
186 u8 *s = *pp;
187 u8 val;
188 val = *s++;
189 *pp = s;
190 return val;
191}
192
193static inline u32 _get_word(void **pp)
194{
195 u8 *s = *pp;
196 u32 val;
197 val = *s++;
198 val |= (*s++ << 8);
199 val |= (*s++ << 16);
200 val |= (*s++ << 24);
201 *pp = s;
202 return val;
203}
204
205static inline u32 _get_slice(void **pp, unsigned char *dp)
206{
207 unsigned int len, i;
208
209 len = i = _get_word(pp);
210 while (i-- > 0) *dp++ = _get_byte(pp);
211 return len;
212}
213
214/* ------------------------------------------------------------- */
215
216void b1dma_reset(avmcard *card)
217{
218 card->csr = 0x0;
219 b1dma_writel(card, card->csr, AMCC_INTCSR);
220 b1dma_writel(card, 0, AMCC_MCSR);
221 b1dma_writel(card, 0, AMCC_RXLEN);
222 b1dma_writel(card, 0, AMCC_TXLEN);
223
224 t1outp(card->port, 0x10, 0x00);
225 t1outp(card->port, 0x07, 0x00);
226
227 b1dma_writel(card, 0, AMCC_MCSR);
228 mdelay(10);
229 b1dma_writel(card, 0x0f000000, AMCC_MCSR); /* reset all */
230 mdelay(10);
231 b1dma_writel(card, 0, AMCC_MCSR);
232 if (card->cardtype == avm_t1pci)
233 mdelay(42);
234 else
235 mdelay(10);
236}
237
238/* ------------------------------------------------------------- */
239
240static int b1dma_detect(avmcard *card)
241{
242 b1dma_writel(card, 0, AMCC_MCSR);
243 mdelay(10);
244 b1dma_writel(card, 0x0f000000, AMCC_MCSR); /* reset all */
245 mdelay(10);
246 b1dma_writel(card, 0, AMCC_MCSR);
247 mdelay(42);
248
249 b1dma_writel(card, 0, AMCC_RXLEN);
250 b1dma_writel(card, 0, AMCC_TXLEN);
251 card->csr = 0x0;
252 b1dma_writel(card, card->csr, AMCC_INTCSR);
253
254 if (b1dma_readl(card, AMCC_MCSR) != 0x000000E6)
255 return 1;
256
257 b1dma_writel(card, 0xffffffff, AMCC_RXPTR);
258 b1dma_writel(card, 0xffffffff, AMCC_TXPTR);
259 if ( b1dma_readl(card, AMCC_RXPTR) != 0xfffffffc
260 || b1dma_readl(card, AMCC_TXPTR) != 0xfffffffc)
261 return 2;
262
263 b1dma_writel(card, 0x0, AMCC_RXPTR);
264 b1dma_writel(card, 0x0, AMCC_TXPTR);
265 if ( b1dma_readl(card, AMCC_RXPTR) != 0x0
266 || b1dma_readl(card, AMCC_TXPTR) != 0x0)
267 return 3;
268
269 t1outp(card->port, 0x10, 0x00);
270 t1outp(card->port, 0x07, 0x00);
271
272 t1outp(card->port, 0x02, 0x02);
273 t1outp(card->port, 0x03, 0x02);
274
275 if ( (t1inp(card->port, 0x02) & 0xFE) != 0x02
276 || t1inp(card->port, 0x3) != 0x03)
277 return 4;
278
279 t1outp(card->port, 0x02, 0x00);
280 t1outp(card->port, 0x03, 0x00);
281
282 if ( (t1inp(card->port, 0x02) & 0xFE) != 0x00
283 || t1inp(card->port, 0x3) != 0x01)
284 return 5;
285
286 return 0;
287}
288
289int t1pci_detect(avmcard *card)
290{
291 int ret;
292
293 if ((ret = b1dma_detect(card)) != 0)
294 return ret;
295
296 /* Transputer test */
297
298 if ( WriteReg(card, 0x80001000, 0x11) != 0
299 || WriteReg(card, 0x80101000, 0x22) != 0
300 || WriteReg(card, 0x80201000, 0x33) != 0
301 || WriteReg(card, 0x80301000, 0x44) != 0)
302 return 6;
303
304 if ( ReadReg(card, 0x80001000) != 0x11
305 || ReadReg(card, 0x80101000) != 0x22
306 || ReadReg(card, 0x80201000) != 0x33
307 || ReadReg(card, 0x80301000) != 0x44)
308 return 7;
309
310 if ( WriteReg(card, 0x80001000, 0x55) != 0
311 || WriteReg(card, 0x80101000, 0x66) != 0
312 || WriteReg(card, 0x80201000, 0x77) != 0
313 || WriteReg(card, 0x80301000, 0x88) != 0)
314 return 8;
315
316 if ( ReadReg(card, 0x80001000) != 0x55
317 || ReadReg(card, 0x80101000) != 0x66
318 || ReadReg(card, 0x80201000) != 0x77
319 || ReadReg(card, 0x80301000) != 0x88)
320 return 9;
321
322 return 0;
323}
324
325int b1pciv4_detect(avmcard *card)
326{
327 int ret, i;
328
329 if ((ret = b1dma_detect(card)) != 0)
330 return ret;
331
332 for (i=0; i < 5 ; i++) {
333 if (WriteReg(card, 0x80A00000, 0x21) != 0)
334 return 6;
335 if ((ReadReg(card, 0x80A00000) & 0x01) != 0x01)
336 return 7;
337 }
338 for (i=0; i < 5 ; i++) {
339 if (WriteReg(card, 0x80A00000, 0x20) != 0)
340 return 8;
341 if ((ReadReg(card, 0x80A00000) & 0x01) != 0x00)
342 return 9;
343 }
344
345 return 0;
346}
347
348static void b1dma_queue_tx(avmcard *card, struct sk_buff *skb)
349{
350 unsigned long flags;
351
352 spin_lock_irqsave(&card->lock, flags);
353
354 skb_queue_tail(&card->dma->send_queue, skb);
355
356 if (!(card->csr & EN_TX_TC_INT)) {
357 b1dma_dispatch_tx(card);
358 b1dma_writel(card, card->csr, AMCC_INTCSR);
359 }
360
361 spin_unlock_irqrestore(&card->lock, flags);
362}
363
364/* ------------------------------------------------------------- */
365
366static void b1dma_dispatch_tx(avmcard *card)
367{
368 avmcard_dmainfo *dma = card->dma;
369 struct sk_buff *skb;
370 u8 cmd, subcmd;
371 u16 len;
372 u32 txlen;
373 void *p;
374
375 skb = skb_dequeue(&dma->send_queue);
376
377 len = CAPIMSG_LEN(skb->data);
378
379 if (len) {
380 cmd = CAPIMSG_COMMAND(skb->data);
381 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
382
383 p = dma->sendbuf.dmabuf;
384
385 if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
386 u16 dlen = CAPIMSG_DATALEN(skb->data);
387 _put_byte(&p, SEND_DATA_B3_REQ);
388 _put_slice(&p, skb->data, len);
389 _put_slice(&p, skb->data + len, dlen);
390 } else {
391 _put_byte(&p, SEND_MESSAGE);
392 _put_slice(&p, skb->data, len);
393 }
394 txlen = (u8 *)p - (u8 *)dma->sendbuf.dmabuf;
395#ifdef CONFIG_B1DMA_DEBUG
396 printk(KERN_DEBUG "tx: put msg len=%d\n", txlen);
397#endif
398 } else {
399 txlen = skb->len-2;
400#ifdef CONFIG_B1DMA_POLLDEBUG
401 if (skb->data[2] == SEND_POLLACK)
402 printk(KERN_INFO "%s: send ack\n", card->name);
403#endif
404#ifdef CONFIG_B1DMA_DEBUG
405 printk(KERN_DEBUG "tx: put 0x%x len=%d\n",
406 skb->data[2], txlen);
407#endif
408 memcpy(dma->sendbuf.dmabuf, skb->data+2, skb->len-2);
409 }
410 txlen = (txlen + 3) & ~3;
411
412 b1dma_writel(card, dma->sendbuf.dmaaddr, AMCC_TXPTR);
413 b1dma_writel(card, txlen, AMCC_TXLEN);
414
415 card->csr |= EN_TX_TC_INT;
416
417 dev_kfree_skb_any(skb);
418}
419
420/* ------------------------------------------------------------- */
421
422static void queue_pollack(avmcard *card)
423{
424 struct sk_buff *skb;
425 void *p;
426
427 skb = alloc_skb(3, GFP_ATOMIC);
428 if (!skb) {
429 printk(KERN_CRIT "%s: no memory, lost poll ack\n",
430 card->name);
431 return;
432 }
433 p = skb->data;
434 _put_byte(&p, 0);
435 _put_byte(&p, 0);
436 _put_byte(&p, SEND_POLLACK);
437 skb_put(skb, (u8 *)p - (u8 *)skb->data);
438
439 b1dma_queue_tx(card, skb);
440}
441
442/* ------------------------------------------------------------- */
443
444static void b1dma_handle_rx(avmcard *card)
445{
446 avmctrl_info *cinfo = &card->ctrlinfo[0];
447 avmcard_dmainfo *dma = card->dma;
448 struct capi_ctr *ctrl = &cinfo->capi_ctrl;
449 struct sk_buff *skb;
450 void *p = dma->recvbuf.dmabuf+4;
451 u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
452 u8 b1cmd = _get_byte(&p);
453
454#ifdef CONFIG_B1DMA_DEBUG
455 printk(KERN_DEBUG "rx: 0x%x %lu\n", b1cmd, (unsigned long)dma->recvlen);
456#endif
457
458 switch (b1cmd) {
459 case RECEIVE_DATA_B3_IND:
460
461 ApplId = (unsigned) _get_word(&p);
462 MsgLen = _get_slice(&p, card->msgbuf);
463 DataB3Len = _get_slice(&p, card->databuf);
464
465 if (MsgLen < 30) { /* not CAPI 64Bit */
466 memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
467 MsgLen = 30;
468 CAPIMSG_SETLEN(card->msgbuf, 30);
469 }
470 if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) {
471 printk(KERN_ERR "%s: incoming packet dropped\n",
472 card->name);
473 } else {
474 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
475 memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
476 capi_ctr_handle_message(ctrl, ApplId, skb);
477 }
478 break;
479
480 case RECEIVE_MESSAGE:
481
482 ApplId = (unsigned) _get_word(&p);
483 MsgLen = _get_slice(&p, card->msgbuf);
484 if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
485 printk(KERN_ERR "%s: incoming packet dropped\n",
486 card->name);
487 } else {
488 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
489 if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF)
490 capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
491 CAPIMSG_NCCI(skb->data),
492 CAPIMSG_MSGID(skb->data));
493
494 capi_ctr_handle_message(ctrl, ApplId, skb);
495 }
496 break;
497
498 case RECEIVE_NEW_NCCI:
499
500 ApplId = _get_word(&p);
501 NCCI = _get_word(&p);
502 WindowSize = _get_word(&p);
503
504 capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
505
506 break;
507
508 case RECEIVE_FREE_NCCI:
509
510 ApplId = _get_word(&p);
511 NCCI = _get_word(&p);
512
513 if (NCCI != 0xffffffff)
514 capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
515
516 break;
517
518 case RECEIVE_START:
519#ifdef CONFIG_B1DMA_POLLDEBUG
520 printk(KERN_INFO "%s: receive poll\n", card->name);
521#endif
522 if (!suppress_pollack)
523 queue_pollack(card);
524 capi_ctr_resume_output(ctrl);
525 break;
526
527 case RECEIVE_STOP:
528 capi_ctr_suspend_output(ctrl);
529 break;
530
531 case RECEIVE_INIT:
532
533 cinfo->versionlen = _get_slice(&p, cinfo->versionbuf);
534 b1_parse_version(cinfo);
535 printk(KERN_INFO "%s: %s-card (%s) now active\n",
536 card->name,
537 cinfo->version[VER_CARDTYPE],
538 cinfo->version[VER_DRIVER]);
539 capi_ctr_ready(ctrl);
540 break;
541
542 case RECEIVE_TASK_READY:
543 ApplId = (unsigned) _get_word(&p);
544 MsgLen = _get_slice(&p, card->msgbuf);
545 card->msgbuf[MsgLen] = 0;
546 while ( MsgLen > 0
547 && ( card->msgbuf[MsgLen-1] == '\n'
548 || card->msgbuf[MsgLen-1] == '\r')) {
549 card->msgbuf[MsgLen-1] = 0;
550 MsgLen--;
551 }
552 printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
553 card->name, ApplId, card->msgbuf);
554 break;
555
556 case RECEIVE_DEBUGMSG:
557 MsgLen = _get_slice(&p, card->msgbuf);
558 card->msgbuf[MsgLen] = 0;
559 while ( MsgLen > 0
560 && ( card->msgbuf[MsgLen-1] == '\n'
561 || card->msgbuf[MsgLen-1] == '\r')) {
562 card->msgbuf[MsgLen-1] = 0;
563 MsgLen--;
564 }
565 printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
566 break;
567
568 default:
569 printk(KERN_ERR "%s: b1dma_interrupt: 0x%x ???\n",
570 card->name, b1cmd);
571 return;
572 }
573}
574
575/* ------------------------------------------------------------- */
576
577static void b1dma_handle_interrupt(avmcard *card)
578{
579 u32 status;
580 u32 newcsr;
581
582 spin_lock(&card->lock);
583
584 status = b1dma_readl(card, AMCC_INTCSR);
585 if ((status & ANY_S5933_INT) == 0) {
586 spin_unlock(&card->lock);
587 return;
588 }
589
590 newcsr = card->csr | (status & ALL_INT);
591 if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT;
592 if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT;
593 b1dma_writel(card, newcsr, AMCC_INTCSR);
594
595 if ((status & RX_TC_INT) != 0) {
596 struct avmcard_dmainfo *dma = card->dma;
597 u32 rxlen;
598 if (card->dma->recvlen == 0) {
599 rxlen = b1dma_readl(card, AMCC_RXLEN);
600 if (rxlen == 0) {
601 dma->recvlen = *((u32 *)dma->recvbuf.dmabuf);
602 rxlen = (dma->recvlen + 3) & ~3;
603 b1dma_writel(card, dma->recvbuf.dmaaddr+4, AMCC_RXPTR);
604 b1dma_writel(card, rxlen, AMCC_RXLEN);
605#ifdef CONFIG_B1DMA_DEBUG
606 } else {
607 printk(KERN_ERR "%s: rx not complete (%d).\n",
608 card->name, rxlen);
609#endif
610 }
611 } else {
612 spin_unlock(&card->lock);
613 b1dma_handle_rx(card);
614 dma->recvlen = 0;
615 spin_lock(&card->lock);
616 b1dma_writel(card, dma->recvbuf.dmaaddr, AMCC_RXPTR);
617 b1dma_writel(card, 4, AMCC_RXLEN);
618 }
619 }
620
621 if ((status & TX_TC_INT) != 0) {
622 if (skb_queue_empty(&card->dma->send_queue))
623 card->csr &= ~EN_TX_TC_INT;
624 else
625 b1dma_dispatch_tx(card);
626 }
627 b1dma_writel(card, card->csr, AMCC_INTCSR);
628
629 spin_unlock(&card->lock);
630}
631
632irqreturn_t b1dma_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
633{
634 avmcard *card = devptr;
635
636 b1dma_handle_interrupt(card);
637 return IRQ_HANDLED;
638}
639
640/* ------------------------------------------------------------- */
641
642static int b1dma_loaded(avmcard *card)
643{
644 unsigned long stop;
645 unsigned char ans;
646 unsigned long tout = 2;
647 unsigned int base = card->port;
648
649 for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
650 if (b1_tx_empty(base))
651 break;
652 }
653 if (!b1_tx_empty(base)) {
654 printk(KERN_ERR "%s: b1dma_loaded: tx err, corrupted t4 file ?\n",
655 card->name);
656 return 0;
657 }
658 b1_put_byte(base, SEND_POLLACK);
659 for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
660 if (b1_rx_full(base)) {
661 if ((ans = b1_get_byte(base)) == RECEIVE_POLLDWORD) {
662 return 1;
663 }
664 printk(KERN_ERR "%s: b1dma_loaded: got 0x%x, firmware not running in dword mode\n", card->name, ans);
665 return 0;
666 }
667 }
668 printk(KERN_ERR "%s: b1dma_loaded: firmware not running\n", card->name);
669 return 0;
670}
671
672/* ------------------------------------------------------------- */
673
674static void b1dma_send_init(avmcard *card)
675{
676 struct sk_buff *skb;
677 void *p;
678
679 skb = alloc_skb(15, GFP_ATOMIC);
680 if (!skb) {
681 printk(KERN_CRIT "%s: no memory, lost register appl.\n",
682 card->name);
683 return;
684 }
685 p = skb->data;
686 _put_byte(&p, 0);
687 _put_byte(&p, 0);
688 _put_byte(&p, SEND_INIT);
689 _put_word(&p, CAPI_MAXAPPL);
690 _put_word(&p, AVM_NCCI_PER_CHANNEL*30);
691 _put_word(&p, card->cardnr - 1);
692 skb_put(skb, (u8 *)p - (u8 *)skb->data);
693
694 b1dma_queue_tx(card, skb);
695}
696
697int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
698{
699 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
700 avmcard *card = cinfo->card;
701 int retval;
702
703 b1dma_reset(card);
704
705 if ((retval = b1_load_t4file(card, &data->firmware))) {
706 b1dma_reset(card);
707 printk(KERN_ERR "%s: failed to load t4file!!\n",
708 card->name);
709 return retval;
710 }
711
712 if (data->configuration.len > 0 && data->configuration.data) {
713 if ((retval = b1_load_config(card, &data->configuration))) {
714 b1dma_reset(card);
715 printk(KERN_ERR "%s: failed to load config!!\n",
716 card->name);
717 return retval;
718 }
719 }
720
721 if (!b1dma_loaded(card)) {
722 b1dma_reset(card);
723 printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
724 return -EIO;
725 }
726
727 card->csr = AVM_FLAG;
728 b1dma_writel(card, card->csr, AMCC_INTCSR);
729 b1dma_writel(card, EN_A2P_TRANSFERS|EN_P2A_TRANSFERS|A2P_HI_PRIORITY|
730 P2A_HI_PRIORITY|RESET_A2P_FLAGS|RESET_P2A_FLAGS,
731 AMCC_MCSR);
732 t1outp(card->port, 0x07, 0x30);
733 t1outp(card->port, 0x10, 0xF0);
734
735 card->dma->recvlen = 0;
736 b1dma_writel(card, card->dma->recvbuf.dmaaddr, AMCC_RXPTR);
737 b1dma_writel(card, 4, AMCC_RXLEN);
738 card->csr |= EN_RX_TC_INT;
739 b1dma_writel(card, card->csr, AMCC_INTCSR);
740
741 b1dma_send_init(card);
742
743 return 0;
744}
745
746void b1dma_reset_ctr(struct capi_ctr *ctrl)
747{
748 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
749 avmcard *card = cinfo->card;
750 unsigned long flags;
751
752 spin_lock_irqsave(&card->lock, flags);
753 b1dma_reset(card);
754 spin_unlock_irqrestore(&card->lock, flags);
755
756 memset(cinfo->version, 0, sizeof(cinfo->version));
757 capilib_release(&cinfo->ncci_head);
758 capi_ctr_reseted(ctrl);
759}
760
761/* ------------------------------------------------------------- */
762
763void b1dma_register_appl(struct capi_ctr *ctrl,
764 u16 appl,
765 capi_register_params *rp)
766{
767 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
768 avmcard *card = cinfo->card;
769 struct sk_buff *skb;
770 int want = rp->level3cnt;
771 int nconn;
772 void *p;
773
774 if (want > 0) nconn = want;
775 else nconn = ctrl->profile.nbchannel * -want;
776 if (nconn == 0) nconn = ctrl->profile.nbchannel;
777
778 skb = alloc_skb(23, GFP_ATOMIC);
779 if (!skb) {
780 printk(KERN_CRIT "%s: no memory, lost register appl.\n",
781 card->name);
782 return;
783 }
784 p = skb->data;
785 _put_byte(&p, 0);
786 _put_byte(&p, 0);
787 _put_byte(&p, SEND_REGISTER);
788 _put_word(&p, appl);
789 _put_word(&p, 1024 * (nconn+1));
790 _put_word(&p, nconn);
791 _put_word(&p, rp->datablkcnt);
792 _put_word(&p, rp->datablklen);
793 skb_put(skb, (u8 *)p - (u8 *)skb->data);
794
795 b1dma_queue_tx(card, skb);
796}
797
798/* ------------------------------------------------------------- */
799
800void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl)
801{
802 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
803 avmcard *card = cinfo->card;
804 struct sk_buff *skb;
805 void *p;
806
807 capilib_release_appl(&cinfo->ncci_head, appl);
808
809 skb = alloc_skb(7, GFP_ATOMIC);
810 if (!skb) {
811 printk(KERN_CRIT "%s: no memory, lost release appl.\n",
812 card->name);
813 return;
814 }
815 p = skb->data;
816 _put_byte(&p, 0);
817 _put_byte(&p, 0);
818 _put_byte(&p, SEND_RELEASE);
819 _put_word(&p, appl);
820
821 skb_put(skb, (u8 *)p - (u8 *)skb->data);
822
823 b1dma_queue_tx(card, skb);
824}
825
826/* ------------------------------------------------------------- */
827
828u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
829{
830 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
831 avmcard *card = cinfo->card;
832 u16 retval = CAPI_NOERROR;
833
834 if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
835 retval = capilib_data_b3_req(&cinfo->ncci_head,
836 CAPIMSG_APPID(skb->data),
837 CAPIMSG_NCCI(skb->data),
838 CAPIMSG_MSGID(skb->data));
839 }
840 if (retval == CAPI_NOERROR)
841 b1dma_queue_tx(card, skb);
842
843 return retval;
844}
845
846/* ------------------------------------------------------------- */
847
848int b1dmactl_read_proc(char *page, char **start, off_t off,
849 int count, int *eof, struct capi_ctr *ctrl)
850{
851 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
852 avmcard *card = cinfo->card;
853 u8 flag;
854 int len = 0;
855 char *s;
856 u32 txoff, txlen, rxoff, rxlen, csr;
857 unsigned long flags;
858
859 len += sprintf(page+len, "%-16s %s\n", "name", card->name);
860 len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
861 len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
862 len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase);
863 switch (card->cardtype) {
864 case avm_b1isa: s = "B1 ISA"; break;
865 case avm_b1pci: s = "B1 PCI"; break;
866 case avm_b1pcmcia: s = "B1 PCMCIA"; break;
867 case avm_m1: s = "M1"; break;
868 case avm_m2: s = "M2"; break;
869 case avm_t1isa: s = "T1 ISA (HEMA)"; break;
870 case avm_t1pci: s = "T1 PCI"; break;
871 case avm_c4: s = "C4"; break;
872 case avm_c2: s = "C2"; break;
873 default: s = "???"; break;
874 }
875 len += sprintf(page+len, "%-16s %s\n", "type", s);
876 if ((s = cinfo->version[VER_DRIVER]) != 0)
877 len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
878 if ((s = cinfo->version[VER_CARDTYPE]) != 0)
879 len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
880 if ((s = cinfo->version[VER_SERIAL]) != 0)
881 len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
882
883 if (card->cardtype != avm_m1) {
884 flag = ((u8 *)(ctrl->profile.manu))[3];
885 if (flag)
886 len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n",
887 "protocol",
888 (flag & 0x01) ? " DSS1" : "",
889 (flag & 0x02) ? " CT1" : "",
890 (flag & 0x04) ? " VN3" : "",
891 (flag & 0x08) ? " NI1" : "",
892 (flag & 0x10) ? " AUSTEL" : "",
893 (flag & 0x20) ? " ESS" : "",
894 (flag & 0x40) ? " 1TR6" : ""
895 );
896 }
897 if (card->cardtype != avm_m1) {
898 flag = ((u8 *)(ctrl->profile.manu))[5];
899 if (flag)
900 len += sprintf(page+len, "%-16s%s%s%s%s\n",
901 "linetype",
902 (flag & 0x01) ? " point to point" : "",
903 (flag & 0x02) ? " point to multipoint" : "",
904 (flag & 0x08) ? " leased line without D-channel" : "",
905 (flag & 0x04) ? " leased line with D-channel" : ""
906 );
907 }
908 len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
909
910
911 spin_lock_irqsave(&card->lock, flags);
912
913 txoff = (dma_addr_t)b1dma_readl(card, AMCC_TXPTR)-card->dma->sendbuf.dmaaddr;
914 txlen = b1dma_readl(card, AMCC_TXLEN);
915
916 rxoff = (dma_addr_t)b1dma_readl(card, AMCC_RXPTR)-card->dma->recvbuf.dmaaddr;
917 rxlen = b1dma_readl(card, AMCC_RXLEN);
918
919 csr = b1dma_readl(card, AMCC_INTCSR);
920
921 spin_unlock_irqrestore(&card->lock, flags);
922
923 len += sprintf(page+len, "%-16s 0x%lx\n",
924 "csr (cached)", (unsigned long)card->csr);
925 len += sprintf(page+len, "%-16s 0x%lx\n",
926 "csr", (unsigned long)csr);
927 len += sprintf(page+len, "%-16s %lu\n",
928 "txoff", (unsigned long)txoff);
929 len += sprintf(page+len, "%-16s %lu\n",
930 "txlen", (unsigned long)txlen);
931 len += sprintf(page+len, "%-16s %lu\n",
932 "rxoff", (unsigned long)rxoff);
933 len += sprintf(page+len, "%-16s %lu\n",
934 "rxlen", (unsigned long)rxlen);
935
936 if (off+count >= len)
937 *eof = 1;
938 if (len < off)
939 return 0;
940 *start = page + off;
941 return ((count < len-off) ? count : len-off);
942}
943
944/* ------------------------------------------------------------- */
945
946EXPORT_SYMBOL(b1dma_reset);
947EXPORT_SYMBOL(t1pci_detect);
948EXPORT_SYMBOL(b1pciv4_detect);
949EXPORT_SYMBOL(b1dma_interrupt);
950
951EXPORT_SYMBOL(b1dma_load_firmware);
952EXPORT_SYMBOL(b1dma_reset_ctr);
953EXPORT_SYMBOL(b1dma_register_appl);
954EXPORT_SYMBOL(b1dma_release_appl);
955EXPORT_SYMBOL(b1dma_send_message);
956EXPORT_SYMBOL(b1dmactl_read_proc);
957
958int b1dma_init(void)
959{
960 char *p;
961 char rev[32];
962
963 if ((p = strchr(revision, ':')) != 0 && p[1]) {
964 strlcpy(rev, p + 2, sizeof(rev));
965 if ((p = strchr(rev, '$')) != 0 && p > rev)
966 *(p-1) = 0;
967 } else
968 strcpy(rev, "1.0");
969
970 printk(KERN_INFO "b1dma: revision %s\n", rev);
971
972 return 0;
973}
974
975void b1dma_exit(void)
976{
977}
978
979module_init(b1dma_init);
980module_exit(b1dma_exit);
diff --git a/drivers/isdn/hardware/avm/b1isa.c b/drivers/isdn/hardware/avm/b1isa.c
new file mode 100644
index 000000000000..38bd4dfecbd1
--- /dev/null
+++ b/drivers/isdn/hardware/avm/b1isa.c
@@ -0,0 +1,245 @@
1/* $Id: b1isa.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $
2 *
3 * Module for AVM B1 ISA-card.
4 *
5 * Copyright 1999 by Carsten Paeth <calle@calle.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/skbuff.h>
15#include <linux/delay.h>
16#include <linux/mm.h>
17#include <linux/interrupt.h>
18#include <linux/ioport.h>
19#include <linux/capi.h>
20#include <linux/init.h>
21#include <linux/pci.h>
22#include <asm/io.h>
23#include <linux/isdn/capicmd.h>
24#include <linux/isdn/capiutil.h>
25#include <linux/isdn/capilli.h>
26#include "avmcard.h"
27
28/* ------------------------------------------------------------- */
29
30static char *revision = "$Revision: 1.1.2.3 $";
31
32/* ------------------------------------------------------------- */
33
34MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 ISA card");
35MODULE_AUTHOR("Carsten Paeth");
36MODULE_LICENSE("GPL");
37
38/* ------------------------------------------------------------- */
39
40static void b1isa_remove(struct pci_dev *pdev)
41{
42 avmctrl_info *cinfo = pci_get_drvdata(pdev);
43 avmcard *card;
44
45 if (!cinfo)
46 return;
47
48 card = cinfo->card;
49
50 b1_reset(card->port);
51 b1_reset(card->port);
52
53 detach_capi_ctr(&cinfo->capi_ctrl);
54 free_irq(card->irq, card);
55 release_region(card->port, AVMB1_PORTLEN);
56 b1_free_card(card);
57}
58
59/* ------------------------------------------------------------- */
60
61static char *b1isa_procinfo(struct capi_ctr *ctrl);
62
63static int b1isa_probe(struct pci_dev *pdev)
64{
65 avmctrl_info *cinfo;
66 avmcard *card;
67 int retval;
68
69 card = b1_alloc_card(1);
70 if (!card) {
71 printk(KERN_WARNING "b1isa: no memory.\n");
72 retval = -ENOMEM;
73 goto err;
74 }
75
76 cinfo = card->ctrlinfo;
77
78 card->port = pci_resource_start(pdev, 0);
79 card->irq = pdev->irq;
80 card->cardtype = avm_b1isa;
81 sprintf(card->name, "b1isa-%x", card->port);
82
83 if ( card->port != 0x150 && card->port != 0x250
84 && card->port != 0x300 && card->port != 0x340) {
85 printk(KERN_WARNING "b1isa: invalid port 0x%x.\n", card->port);
86 retval = -EINVAL;
87 goto err_free;
88 }
89 if (b1_irq_table[card->irq & 0xf] == 0) {
90 printk(KERN_WARNING "b1isa: irq %d not valid.\n", card->irq);
91 retval = -EINVAL;
92 goto err_free;
93 }
94 if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
95 printk(KERN_WARNING "b1isa: ports 0x%03x-0x%03x in use.\n",
96 card->port, card->port + AVMB1_PORTLEN);
97 retval = -EBUSY;
98 goto err_free;
99 }
100 retval = request_irq(card->irq, b1_interrupt, 0, card->name, card);
101 if (retval) {
102 printk(KERN_ERR "b1isa: unable to get IRQ %d.\n", card->irq);
103 goto err_release_region;
104 }
105 b1_reset(card->port);
106 if ((retval = b1_detect(card->port, card->cardtype)) != 0) {
107 printk(KERN_NOTICE "b1isa: NO card at 0x%x (%d)\n",
108 card->port, retval);
109 retval = -ENODEV;
110 goto err_free_irq;
111 }
112 b1_reset(card->port);
113 b1_getrevision(card);
114
115 cinfo->capi_ctrl.owner = THIS_MODULE;
116 cinfo->capi_ctrl.driver_name = "b1isa";
117 cinfo->capi_ctrl.driverdata = cinfo;
118 cinfo->capi_ctrl.register_appl = b1_register_appl;
119 cinfo->capi_ctrl.release_appl = b1_release_appl;
120 cinfo->capi_ctrl.send_message = b1_send_message;
121 cinfo->capi_ctrl.load_firmware = b1_load_firmware;
122 cinfo->capi_ctrl.reset_ctr = b1_reset_ctr;
123 cinfo->capi_ctrl.procinfo = b1isa_procinfo;
124 cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc;
125 strcpy(cinfo->capi_ctrl.name, card->name);
126
127 retval = attach_capi_ctr(&cinfo->capi_ctrl);
128 if (retval) {
129 printk(KERN_ERR "b1isa: attach controller failed.\n");
130 goto err_free_irq;
131 }
132
133 printk(KERN_INFO "b1isa: AVM B1 ISA at i/o %#x, irq %d, revision %d\n",
134 card->port, card->irq, card->revision);
135
136 pci_set_drvdata(pdev, cinfo);
137 return 0;
138
139 err_free_irq:
140 free_irq(card->irq, card);
141 err_release_region:
142 release_region(card->port, AVMB1_PORTLEN);
143 err_free:
144 b1_free_card(card);
145 err:
146 return retval;
147}
148
149static char *b1isa_procinfo(struct capi_ctr *ctrl)
150{
151 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
152
153 if (!cinfo)
154 return "";
155 sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d",
156 cinfo->cardname[0] ? cinfo->cardname : "-",
157 cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
158 cinfo->card ? cinfo->card->port : 0x0,
159 cinfo->card ? cinfo->card->irq : 0,
160 cinfo->card ? cinfo->card->revision : 0
161 );
162 return cinfo->infobuf;
163}
164
165/* ------------------------------------------------------------- */
166
167#define MAX_CARDS 4
168static struct pci_dev isa_dev[MAX_CARDS];
169static int io[MAX_CARDS];
170static int irq[MAX_CARDS];
171
172MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i");
173MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i");
174MODULE_PARM_DESC(io, "I/O base address(es)");
175MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
176
177static int b1isa_add_card(struct capi_driver *driver, capicardparams *data)
178{
179 int i;
180
181 for (i = 0; i < MAX_CARDS; i++) {
182 if (isa_dev[i].resource[0].start)
183 continue;
184
185 isa_dev[i].resource[0].start = data->port;
186 isa_dev[i].irq = data->irq;
187
188 if (b1isa_probe(&isa_dev[i]) == 0)
189 return 0;
190 }
191 return -ENODEV;
192}
193
194static struct capi_driver capi_driver_b1isa = {
195 .name = "b1isa",
196 .revision = "1.0",
197 .add_card = b1isa_add_card,
198};
199
200static int __init b1isa_init(void)
201{
202 char *p;
203 char rev[32];
204 int i;
205
206 if ((p = strchr(revision, ':')) != 0 && p[1]) {
207 strlcpy(rev, p + 2, 32);
208 if ((p = strchr(rev, '$')) != 0 && p > rev)
209 *(p-1) = 0;
210 } else
211 strcpy(rev, "1.0");
212
213 for (i = 0; i < MAX_CARDS; i++) {
214 if (!io[i])
215 break;
216
217 isa_dev[i].resource[0].start = io[i];
218 isa_dev[i].irq = irq[i];
219
220 if (b1isa_probe(&isa_dev[i]) != 0)
221 return -ENODEV;
222 }
223
224 strlcpy(capi_driver_b1isa.revision, rev, 32);
225 register_capi_driver(&capi_driver_b1isa);
226 printk(KERN_INFO "b1isa: revision %s\n", rev);
227
228 return 0;
229}
230
231static void __exit b1isa_exit(void)
232{
233 int i;
234
235 for (i = 0; i < MAX_CARDS; i++) {
236 if (!io[i])
237 break;
238
239 b1isa_remove(&isa_dev[i]);
240 }
241 unregister_capi_driver(&capi_driver_b1isa);
242}
243
244module_init(b1isa_init);
245module_exit(b1isa_exit);
diff --git a/drivers/isdn/hardware/avm/b1pci.c b/drivers/isdn/hardware/avm/b1pci.c
new file mode 100644
index 000000000000..5435a6cfb5e7
--- /dev/null
+++ b/drivers/isdn/hardware/avm/b1pci.c
@@ -0,0 +1,417 @@
1/* $Id: b1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
2 *
3 * Module for AVM B1 PCI-card.
4 *
5 * Copyright 1999 by Carsten Paeth <calle@calle.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/config.h>
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/skbuff.h>
16#include <linux/delay.h>
17#include <linux/mm.h>
18#include <linux/interrupt.h>
19#include <linux/ioport.h>
20#include <linux/pci.h>
21#include <linux/capi.h>
22#include <asm/io.h>
23#include <linux/init.h>
24#include <linux/isdn/capicmd.h>
25#include <linux/isdn/capiutil.h>
26#include <linux/isdn/capilli.h>
27#include "avmcard.h"
28
29/* ------------------------------------------------------------- */
30
31static char *revision = "$Revision: 1.1.2.2 $";
32
33/* ------------------------------------------------------------- */
34
35static struct pci_device_id b1pci_pci_tbl[] = {
36 { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, PCI_ANY_ID, PCI_ANY_ID },
37 { } /* Terminating entry */
38};
39
40MODULE_DEVICE_TABLE(pci, b1pci_pci_tbl);
41MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 PCI card");
42MODULE_AUTHOR("Carsten Paeth");
43MODULE_LICENSE("GPL");
44
45/* ------------------------------------------------------------- */
46
47static char *b1pci_procinfo(struct capi_ctr *ctrl)
48{
49 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
50
51 if (!cinfo)
52 return "";
53 sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d",
54 cinfo->cardname[0] ? cinfo->cardname : "-",
55 cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
56 cinfo->card ? cinfo->card->port : 0x0,
57 cinfo->card ? cinfo->card->irq : 0,
58 cinfo->card ? cinfo->card->revision : 0
59 );
60 return cinfo->infobuf;
61}
62
63/* ------------------------------------------------------------- */
64
65static int b1pci_probe(struct capicardparams *p, struct pci_dev *pdev)
66{
67 avmcard *card;
68 avmctrl_info *cinfo;
69 int retval;
70
71 card = b1_alloc_card(1);
72 if (!card) {
73 printk(KERN_WARNING "b1pci: no memory.\n");
74 retval = -ENOMEM;
75 goto err;
76 }
77
78 cinfo = card->ctrlinfo;
79 sprintf(card->name, "b1pci-%x", p->port);
80 card->port = p->port;
81 card->irq = p->irq;
82 card->cardtype = avm_b1pci;
83
84 if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
85 printk(KERN_WARNING "b1pci: ports 0x%03x-0x%03x in use.\n",
86 card->port, card->port + AVMB1_PORTLEN);
87 retval = -EBUSY;
88 goto err_free;
89 }
90 b1_reset(card->port);
91 retval = b1_detect(card->port, card->cardtype);
92 if (retval) {
93 printk(KERN_NOTICE "b1pci: NO card at 0x%x (%d)\n",
94 card->port, retval);
95 retval = -ENODEV;
96 goto err_release_region;
97 }
98 b1_reset(card->port);
99 b1_getrevision(card);
100
101 retval = request_irq(card->irq, b1_interrupt, SA_SHIRQ, card->name, card);
102 if (retval) {
103 printk(KERN_ERR "b1pci: unable to get IRQ %d.\n", card->irq);
104 retval = -EBUSY;
105 goto err_release_region;
106 }
107
108 cinfo->capi_ctrl.driver_name = "b1pci";
109 cinfo->capi_ctrl.driverdata = cinfo;
110 cinfo->capi_ctrl.register_appl = b1_register_appl;
111 cinfo->capi_ctrl.release_appl = b1_release_appl;
112 cinfo->capi_ctrl.send_message = b1_send_message;
113 cinfo->capi_ctrl.load_firmware = b1_load_firmware;
114 cinfo->capi_ctrl.reset_ctr = b1_reset_ctr;
115 cinfo->capi_ctrl.procinfo = b1pci_procinfo;
116 cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc;
117 strcpy(cinfo->capi_ctrl.name, card->name);
118 cinfo->capi_ctrl.owner = THIS_MODULE;
119
120 retval = attach_capi_ctr(&cinfo->capi_ctrl);
121 if (retval) {
122 printk(KERN_ERR "b1pci: attach controller failed.\n");
123 goto err_free_irq;
124 }
125
126 if (card->revision >= 4) {
127 printk(KERN_INFO "b1pci: AVM B1 PCI V4 at i/o %#x, irq %d, revision %d (no dma)\n",
128 card->port, card->irq, card->revision);
129 } else {
130 printk(KERN_INFO "b1pci: AVM B1 PCI at i/o %#x, irq %d, revision %d\n",
131 card->port, card->irq, card->revision);
132 }
133
134 pci_set_drvdata(pdev, card);
135 return 0;
136
137 err_free_irq:
138 free_irq(card->irq, card);
139 err_release_region:
140 release_region(card->port, AVMB1_PORTLEN);
141 err_free:
142 b1_free_card(card);
143 err:
144 return retval;
145}
146
147static void b1pci_remove(struct pci_dev *pdev)
148{
149 avmcard *card = pci_get_drvdata(pdev);
150 avmctrl_info *cinfo = card->ctrlinfo;
151 unsigned int port = card->port;
152
153 b1_reset(port);
154 b1_reset(port);
155
156 detach_capi_ctr(&cinfo->capi_ctrl);
157 free_irq(card->irq, card);
158 release_region(card->port, AVMB1_PORTLEN);
159 b1_free_card(card);
160}
161
162#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
163/* ------------------------------------------------------------- */
164
165static char *b1pciv4_procinfo(struct capi_ctr *ctrl)
166{
167 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
168
169 if (!cinfo)
170 return "";
171 sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx r%d",
172 cinfo->cardname[0] ? cinfo->cardname : "-",
173 cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
174 cinfo->card ? cinfo->card->port : 0x0,
175 cinfo->card ? cinfo->card->irq : 0,
176 cinfo->card ? cinfo->card->membase : 0,
177 cinfo->card ? cinfo->card->revision : 0
178 );
179 return cinfo->infobuf;
180}
181
182/* ------------------------------------------------------------- */
183
184static int b1pciv4_probe(struct capicardparams *p, struct pci_dev *pdev)
185{
186 avmcard *card;
187 avmctrl_info *cinfo;
188 int retval;
189
190 card = b1_alloc_card(1);
191 if (!card) {
192 printk(KERN_WARNING "b1pci: no memory.\n");
193 retval = -ENOMEM;
194 goto err;
195 }
196
197 card->dma = avmcard_dma_alloc("b1pci", pdev, 2048+128, 2048+128);
198 if (!card->dma) {
199 printk(KERN_WARNING "b1pci: dma alloc.\n");
200 retval = -ENOMEM;
201 goto err_free;
202 }
203
204 cinfo = card->ctrlinfo;
205 sprintf(card->name, "b1pciv4-%x", p->port);
206 card->port = p->port;
207 card->irq = p->irq;
208 card->membase = p->membase;
209 card->cardtype = avm_b1pci;
210
211 if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
212 printk(KERN_WARNING "b1pci: ports 0x%03x-0x%03x in use.\n",
213 card->port, card->port + AVMB1_PORTLEN);
214 retval = -EBUSY;
215 goto err_free_dma;
216 }
217
218 card->mbase = ioremap(card->membase, 64);
219 if (!card->mbase) {
220 printk(KERN_NOTICE "b1pci: can't remap memory at 0x%lx\n",
221 card->membase);
222 retval = -ENOMEM;
223 goto err_release_region;
224 }
225
226 b1dma_reset(card);
227
228 retval = b1pciv4_detect(card);
229 if (retval) {
230 printk(KERN_NOTICE "b1pci: NO card at 0x%x (%d)\n",
231 card->port, retval);
232 retval = -ENODEV;
233 goto err_unmap;
234 }
235 b1dma_reset(card);
236 b1_getrevision(card);
237
238 retval = request_irq(card->irq, b1dma_interrupt, SA_SHIRQ, card->name, card);
239 if (retval) {
240 printk(KERN_ERR "b1pci: unable to get IRQ %d.\n",
241 card->irq);
242 retval = -EBUSY;
243 goto err_unmap;
244 }
245
246 cinfo->capi_ctrl.owner = THIS_MODULE;
247 cinfo->capi_ctrl.driver_name = "b1pciv4";
248 cinfo->capi_ctrl.driverdata = cinfo;
249 cinfo->capi_ctrl.register_appl = b1dma_register_appl;
250 cinfo->capi_ctrl.release_appl = b1dma_release_appl;
251 cinfo->capi_ctrl.send_message = b1dma_send_message;
252 cinfo->capi_ctrl.load_firmware = b1dma_load_firmware;
253 cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr;
254 cinfo->capi_ctrl.procinfo = b1pciv4_procinfo;
255 cinfo->capi_ctrl.ctr_read_proc = b1dmactl_read_proc;
256 strcpy(cinfo->capi_ctrl.name, card->name);
257
258 retval = attach_capi_ctr(&cinfo->capi_ctrl);
259 if (retval) {
260 printk(KERN_ERR "b1pci: attach controller failed.\n");
261 goto err_free_irq;
262 }
263 card->cardnr = cinfo->capi_ctrl.cnr;
264
265 printk(KERN_INFO "b1pci: AVM B1 PCI V4 at i/o %#x, irq %d, mem %#lx, revision %d (dma)\n",
266 card->port, card->irq, card->membase, card->revision);
267
268 pci_set_drvdata(pdev, card);
269 return 0;
270
271 err_free_irq:
272 free_irq(card->irq, card);
273 err_unmap:
274 iounmap(card->mbase);
275 err_release_region:
276 release_region(card->port, AVMB1_PORTLEN);
277 err_free_dma:
278 avmcard_dma_free(card->dma);
279 err_free:
280 b1_free_card(card);
281 err:
282 return retval;
283
284}
285
286static void b1pciv4_remove(struct pci_dev *pdev)
287{
288 avmcard *card = pci_get_drvdata(pdev);
289 avmctrl_info *cinfo = card->ctrlinfo;
290
291 b1dma_reset(card);
292
293 detach_capi_ctr(&cinfo->capi_ctrl);
294 free_irq(card->irq, card);
295 iounmap(card->mbase);
296 release_region(card->port, AVMB1_PORTLEN);
297 avmcard_dma_free(card->dma);
298 b1_free_card(card);
299}
300
301#endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */
302
303static int __devinit b1pci_pci_probe(struct pci_dev *pdev,
304 const struct pci_device_id *ent)
305{
306 struct capicardparams param;
307 int retval;
308
309 if (pci_enable_device(pdev) < 0) {
310 printk(KERN_ERR "b1pci: failed to enable AVM-B1\n");
311 return -ENODEV;
312 }
313 param.irq = pdev->irq;
314
315 if (pci_resource_start(pdev, 2)) { /* B1 PCI V4 */
316#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
317 pci_set_master(pdev);
318#endif
319 param.membase = pci_resource_start(pdev, 0);
320 param.port = pci_resource_start(pdev, 2);
321
322 printk(KERN_INFO "b1pci: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n",
323 param.port, param.irq, param.membase);
324#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
325 retval = b1pciv4_probe(&param, pdev);
326#else
327 retval = b1pci_probe(&param, pdev);
328#endif
329 if (retval != 0) {
330 printk(KERN_ERR "b1pci: no AVM-B1 V4 at i/o %#x, irq %d, mem %#x detected\n",
331 param.port, param.irq, param.membase);
332 }
333 } else {
334 param.membase = 0;
335 param.port = pci_resource_start(pdev, 1);
336
337 printk(KERN_INFO "b1pci: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
338 param.port, param.irq);
339 retval = b1pci_probe(&param, pdev);
340 if (retval != 0) {
341 printk(KERN_ERR "b1pci: no AVM-B1 at i/o %#x, irq %d detected\n",
342 param.port, param.irq);
343 }
344 }
345 return retval;
346}
347
348static void __devexit b1pci_pci_remove(struct pci_dev *pdev)
349{
350#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
351 avmcard *card = pci_get_drvdata(pdev);
352
353 if (card->dma)
354 b1pciv4_remove(pdev);
355 else
356 b1pci_remove(pdev);
357#else
358 b1pci_remove(pdev);
359#endif
360}
361
362static struct pci_driver b1pci_pci_driver = {
363 .name = "b1pci",
364 .id_table = b1pci_pci_tbl,
365 .probe = b1pci_pci_probe,
366 .remove = __devexit_p(b1pci_pci_remove),
367};
368
369static struct capi_driver capi_driver_b1pci = {
370 .name = "b1pci",
371 .revision = "1.0",
372};
373#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
374static struct capi_driver capi_driver_b1pciv4 = {
375 .name = "b1pciv4",
376 .revision = "1.0",
377};
378#endif
379
380static int __init b1pci_init(void)
381{
382 char *p;
383 char rev[32];
384 int err;
385
386 if ((p = strchr(revision, ':')) != 0 && p[1]) {
387 strlcpy(rev, p + 2, 32);
388 if ((p = strchr(rev, '$')) != 0 && p > rev)
389 *(p-1) = 0;
390 } else
391 strcpy(rev, "1.0");
392
393
394 err = pci_register_driver(&b1pci_pci_driver);
395 if (!err) {
396 strlcpy(capi_driver_b1pci.revision, rev, 32);
397 register_capi_driver(&capi_driver_b1pci);
398#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
399 strlcpy(capi_driver_b1pciv4.revision, rev, 32);
400 register_capi_driver(&capi_driver_b1pciv4);
401#endif
402 printk(KERN_INFO "b1pci: revision %s\n", rev);
403 }
404 return err;
405}
406
407static void __exit b1pci_exit(void)
408{
409 unregister_capi_driver(&capi_driver_b1pci);
410#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
411 unregister_capi_driver(&capi_driver_b1pciv4);
412#endif
413 pci_unregister_driver(&b1pci_pci_driver);
414}
415
416module_init(b1pci_init);
417module_exit(b1pci_exit);
diff --git a/drivers/isdn/hardware/avm/b1pcmcia.c b/drivers/isdn/hardware/avm/b1pcmcia.c
new file mode 100644
index 000000000000..9746cc5ffff8
--- /dev/null
+++ b/drivers/isdn/hardware/avm/b1pcmcia.c
@@ -0,0 +1,224 @@
1/* $Id: b1pcmcia.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
2 *
3 * Module for AVM B1/M1/M2 PCMCIA-card.
4 *
5 * Copyright 1999 by Carsten Paeth <calle@calle.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/skbuff.h>
15#include <linux/delay.h>
16#include <linux/mm.h>
17#include <linux/interrupt.h>
18#include <linux/ioport.h>
19#include <linux/init.h>
20#include <asm/io.h>
21#include <linux/capi.h>
22#include <linux/b1pcmcia.h>
23#include <linux/isdn/capicmd.h>
24#include <linux/isdn/capiutil.h>
25#include <linux/isdn/capilli.h>
26#include "avmcard.h"
27
28/* ------------------------------------------------------------- */
29
30static char *revision = "$Revision: 1.1.2.2 $";
31
32/* ------------------------------------------------------------- */
33
34MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM PCMCIA cards");
35MODULE_AUTHOR("Carsten Paeth");
36MODULE_LICENSE("GPL");
37
38/* ------------------------------------------------------------- */
39
40static void b1pcmcia_remove_ctr(struct capi_ctr *ctrl)
41{
42 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
43 avmcard *card = cinfo->card;
44 unsigned int port = card->port;
45
46 b1_reset(port);
47 b1_reset(port);
48
49 detach_capi_ctr(ctrl);
50 free_irq(card->irq, card);
51 b1_free_card(card);
52}
53
54/* ------------------------------------------------------------- */
55
56static LIST_HEAD(cards);
57
58static char *b1pcmcia_procinfo(struct capi_ctr *ctrl);
59
60static int b1pcmcia_add_card(unsigned int port, unsigned irq,
61 enum avmcardtype cardtype)
62{
63 avmctrl_info *cinfo;
64 avmcard *card;
65 char *cardname;
66 int retval;
67
68 card = b1_alloc_card(1);
69 if (!card) {
70 printk(KERN_WARNING "b1pcmcia: no memory.\n");
71 retval = -ENOMEM;
72 goto err;
73 }
74 cinfo = card->ctrlinfo;
75
76 switch (cardtype) {
77 case avm_m1: sprintf(card->name, "m1-%x", port); break;
78 case avm_m2: sprintf(card->name, "m2-%x", port); break;
79 default: sprintf(card->name, "b1pcmcia-%x", port); break;
80 }
81 card->port = port;
82 card->irq = irq;
83 card->cardtype = cardtype;
84
85 retval = request_irq(card->irq, b1_interrupt, 0, card->name, card);
86 if (retval) {
87 printk(KERN_ERR "b1pcmcia: unable to get IRQ %d.\n",
88 card->irq);
89 retval = -EBUSY;
90 goto err_free;
91 }
92 b1_reset(card->port);
93 if ((retval = b1_detect(card->port, card->cardtype)) != 0) {
94 printk(KERN_NOTICE "b1pcmcia: NO card at 0x%x (%d)\n",
95 card->port, retval);
96 retval = -ENODEV;
97 goto err_free_irq;
98 }
99 b1_reset(card->port);
100 b1_getrevision(card);
101
102 cinfo->capi_ctrl.owner = THIS_MODULE;
103 cinfo->capi_ctrl.driver_name = "b1pcmcia";
104 cinfo->capi_ctrl.driverdata = cinfo;
105 cinfo->capi_ctrl.register_appl = b1_register_appl;
106 cinfo->capi_ctrl.release_appl = b1_release_appl;
107 cinfo->capi_ctrl.send_message = b1_send_message;
108 cinfo->capi_ctrl.load_firmware = b1_load_firmware;
109 cinfo->capi_ctrl.reset_ctr = b1_reset_ctr;
110 cinfo->capi_ctrl.procinfo = b1pcmcia_procinfo;
111 cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc;
112 strcpy(cinfo->capi_ctrl.name, card->name);
113
114 retval = attach_capi_ctr(&cinfo->capi_ctrl);
115 if (retval) {
116 printk(KERN_ERR "b1pcmcia: attach controller failed.\n");
117 goto err_free_irq;
118 }
119 switch (cardtype) {
120 case avm_m1: cardname = "M1"; break;
121 case avm_m2: cardname = "M2"; break;
122 default : cardname = "B1 PCMCIA"; break;
123 }
124
125 printk(KERN_INFO "b1pcmcia: AVM %s at i/o %#x, irq %d, revision %d\n",
126 cardname, card->port, card->irq, card->revision);
127
128 list_add(&card->list, &cards);
129 return cinfo->capi_ctrl.cnr;
130
131 err_free_irq:
132 free_irq(card->irq, card);
133 err_free:
134 b1_free_card(card);
135 err:
136 return retval;
137}
138
139/* ------------------------------------------------------------- */
140
141static char *b1pcmcia_procinfo(struct capi_ctr *ctrl)
142{
143 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
144
145 if (!cinfo)
146 return "";
147 sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d",
148 cinfo->cardname[0] ? cinfo->cardname : "-",
149 cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
150 cinfo->card ? cinfo->card->port : 0x0,
151 cinfo->card ? cinfo->card->irq : 0,
152 cinfo->card ? cinfo->card->revision : 0
153 );
154 return cinfo->infobuf;
155}
156
157/* ------------------------------------------------------------- */
158
159int b1pcmcia_addcard_b1(unsigned int port, unsigned irq)
160{
161 return b1pcmcia_add_card(port, irq, avm_b1pcmcia);
162}
163
164int b1pcmcia_addcard_m1(unsigned int port, unsigned irq)
165{
166 return b1pcmcia_add_card(port, irq, avm_m1);
167}
168
169int b1pcmcia_addcard_m2(unsigned int port, unsigned irq)
170{
171 return b1pcmcia_add_card(port, irq, avm_m2);
172}
173
174int b1pcmcia_delcard(unsigned int port, unsigned irq)
175{
176 struct list_head *l;
177 avmcard *card;
178
179 list_for_each(l, &cards) {
180 card = list_entry(l, avmcard, list);
181 if (card->port == port && card->irq == irq) {
182 b1pcmcia_remove_ctr(&card->ctrlinfo[0].capi_ctrl);
183 return 0;
184 }
185 }
186 return -ESRCH;
187}
188
189EXPORT_SYMBOL(b1pcmcia_addcard_b1);
190EXPORT_SYMBOL(b1pcmcia_addcard_m1);
191EXPORT_SYMBOL(b1pcmcia_addcard_m2);
192EXPORT_SYMBOL(b1pcmcia_delcard);
193
194static struct capi_driver capi_driver_b1pcmcia = {
195 .name = "b1pcmcia",
196 .revision = "1.0",
197};
198
199static int __init b1pcmcia_init(void)
200{
201 char *p;
202 char rev[32];
203
204 if ((p = strchr(revision, ':')) != 0 && p[1]) {
205 strlcpy(rev, p + 2, 32);
206 if ((p = strchr(rev, '$')) != 0 && p > rev)
207 *(p-1) = 0;
208 } else
209 strcpy(rev, "1.0");
210
211 strlcpy(capi_driver_b1pcmcia.revision, rev, 32);
212 register_capi_driver(&capi_driver_b1pcmcia);
213 printk(KERN_INFO "b1pci: revision %s\n", rev);
214
215 return 0;
216}
217
218static void __exit b1pcmcia_exit(void)
219{
220 unregister_capi_driver(&capi_driver_b1pcmcia);
221}
222
223module_init(b1pcmcia_init);
224module_exit(b1pcmcia_exit);
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
new file mode 100644
index 000000000000..fa6b93b1a42d
--- /dev/null
+++ b/drivers/isdn/hardware/avm/c4.c
@@ -0,0 +1,1310 @@
1/* $Id: c4.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
2 *
3 * Module for AVM C4 & C2 card.
4 *
5 * Copyright 1999 by Carsten Paeth <calle@calle.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/config.h>
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/skbuff.h>
16#include <linux/delay.h>
17#include <linux/mm.h>
18#include <linux/interrupt.h>
19#include <linux/ioport.h>
20#include <linux/pci.h>
21#include <linux/capi.h>
22#include <linux/kernelcapi.h>
23#include <linux/init.h>
24#include <asm/io.h>
25#include <asm/uaccess.h>
26#include <linux/netdevice.h>
27#include <linux/isdn/capicmd.h>
28#include <linux/isdn/capiutil.h>
29#include <linux/isdn/capilli.h>
30#include "avmcard.h"
31
32#undef CONFIG_C4_DEBUG
33#undef CONFIG_C4_POLLDEBUG
34
35/* ------------------------------------------------------------- */
36
37static char *revision = "$Revision: 1.1.2.2 $";
38
39/* ------------------------------------------------------------- */
40
41static int suppress_pollack;
42
43static struct pci_device_id c4_pci_tbl[] = {
44 { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4, 0, 0, (unsigned long)4 },
45 { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C2, 0, 0, (unsigned long)2 },
46 { } /* Terminating entry */
47};
48
49MODULE_DEVICE_TABLE(pci, c4_pci_tbl);
50MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM C2/C4 cards");
51MODULE_AUTHOR("Carsten Paeth");
52MODULE_LICENSE("GPL");
53MODULE_PARM(suppress_pollack, "0-1i");
54
55/* ------------------------------------------------------------- */
56
57static void c4_dispatch_tx(avmcard *card);
58
59/* ------------------------------------------------------------- */
60
61#define DC21285_DRAM_A0MR 0x40000000
62#define DC21285_DRAM_A1MR 0x40004000
63#define DC21285_DRAM_A2MR 0x40008000
64#define DC21285_DRAM_A3MR 0x4000C000
65
66#define CAS_OFFSET 0x88
67
68#define DC21285_ARMCSR_BASE 0x42000000
69
70#define PCI_OUT_INT_STATUS 0x30
71#define PCI_OUT_INT_MASK 0x34
72#define MAILBOX_0 0x50
73#define MAILBOX_1 0x54
74#define MAILBOX_2 0x58
75#define MAILBOX_3 0x5C
76#define DOORBELL 0x60
77#define DOORBELL_SETUP 0x64
78
79#define CHAN_1_CONTROL 0x90
80#define CHAN_2_CONTROL 0xB0
81#define DRAM_TIMING 0x10C
82#define DRAM_ADDR_SIZE_0 0x110
83#define DRAM_ADDR_SIZE_1 0x114
84#define DRAM_ADDR_SIZE_2 0x118
85#define DRAM_ADDR_SIZE_3 0x11C
86#define SA_CONTROL 0x13C
87#define XBUS_CYCLE 0x148
88#define XBUS_STROBE 0x14C
89#define DBELL_PCI_MASK 0x150
90#define DBELL_SA_MASK 0x154
91
92#define SDRAM_SIZE 0x1000000
93
94/* ------------------------------------------------------------- */
95
96#define MBOX_PEEK_POKE MAILBOX_0
97
98#define DBELL_ADDR 0x01
99#define DBELL_DATA 0x02
100#define DBELL_RNWR 0x40
101#define DBELL_INIT 0x80
102
103/* ------------------------------------------------------------- */
104
105#define MBOX_UP_ADDR MAILBOX_0
106#define MBOX_UP_LEN MAILBOX_1
107#define MBOX_DOWN_ADDR MAILBOX_2
108#define MBOX_DOWN_LEN MAILBOX_3
109
110#define DBELL_UP_HOST 0x00000100
111#define DBELL_UP_ARM 0x00000200
112#define DBELL_DOWN_HOST 0x00000400
113#define DBELL_DOWN_ARM 0x00000800
114#define DBELL_RESET_HOST 0x40000000
115#define DBELL_RESET_ARM 0x80000000
116
117/* ------------------------------------------------------------- */
118
119#define DRAM_TIMING_DEF 0x001A01A5
120#define DRAM_AD_SZ_DEF0 0x00000045
121#define DRAM_AD_SZ_NULL 0x00000000
122
123#define SA_CTL_ALLRIGHT 0x64AA0271
124
125#define INIT_XBUS_CYCLE 0x100016DB
126#define INIT_XBUS_STROBE 0xF1F1F1F1
127
128/* ------------------------------------------------------------- */
129
130#define RESET_TIMEOUT (15*HZ) /* 15 sec */
131#define PEEK_POKE_TIMEOUT (HZ/10) /* 0.1 sec */
132
133/* ------------------------------------------------------------- */
134
135#define c4outmeml(addr, value) writel(value, addr)
136#define c4inmeml(addr) readl(addr)
137#define c4outmemw(addr, value) writew(value, addr)
138#define c4inmemw(addr) readw(addr)
139#define c4outmemb(addr, value) writeb(value, addr)
140#define c4inmemb(addr) readb(addr)
141
142/* ------------------------------------------------------------- */
143
144static inline int wait_for_doorbell(avmcard *card, unsigned long t)
145{
146 unsigned long stop;
147
148 stop = jiffies + t;
149 while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) {
150 if (!time_before(jiffies, stop))
151 return -1;
152 mb();
153 }
154 return 0;
155}
156
157static int c4_poke(avmcard *card, unsigned long off, unsigned long value)
158{
159
160 if (wait_for_doorbell(card, HZ/10) < 0)
161 return -1;
162
163 c4outmeml(card->mbase+MBOX_PEEK_POKE, off);
164 c4outmeml(card->mbase+DOORBELL, DBELL_ADDR);
165
166 if (wait_for_doorbell(card, HZ/10) < 0)
167 return -1;
168
169 c4outmeml(card->mbase+MBOX_PEEK_POKE, value);
170 c4outmeml(card->mbase+DOORBELL, DBELL_DATA | DBELL_ADDR);
171
172 return 0;
173}
174
175static int c4_peek(avmcard *card, unsigned long off, unsigned long *valuep)
176{
177 if (wait_for_doorbell(card, HZ/10) < 0)
178 return -1;
179
180 c4outmeml(card->mbase+MBOX_PEEK_POKE, off);
181 c4outmeml(card->mbase+DOORBELL, DBELL_RNWR | DBELL_ADDR);
182
183 if (wait_for_doorbell(card, HZ/10) < 0)
184 return -1;
185
186 *valuep = c4inmeml(card->mbase+MBOX_PEEK_POKE);
187
188 return 0;
189}
190
191/* ------------------------------------------------------------- */
192
193static int c4_load_t4file(avmcard *card, capiloaddatapart * t4file)
194{
195 u32 val;
196 unsigned char *dp;
197 u_int left;
198 u32 loadoff = 0;
199
200 dp = t4file->data;
201 left = t4file->len;
202 while (left >= sizeof(u32)) {
203 if (t4file->user) {
204 if (copy_from_user(&val, dp, sizeof(val)))
205 return -EFAULT;
206 } else {
207 memcpy(&val, dp, sizeof(val));
208 }
209 if (c4_poke(card, loadoff, val)) {
210 printk(KERN_ERR "%s: corrupted firmware file ?\n",
211 card->name);
212 return -EIO;
213 }
214 left -= sizeof(u32);
215 dp += sizeof(u32);
216 loadoff += sizeof(u32);
217 }
218 if (left) {
219 val = 0;
220 if (t4file->user) {
221 if (copy_from_user(&val, dp, left))
222 return -EFAULT;
223 } else {
224 memcpy(&val, dp, left);
225 }
226 if (c4_poke(card, loadoff, val)) {
227 printk(KERN_ERR "%s: corrupted firmware file ?\n",
228 card->name);
229 return -EIO;
230 }
231 }
232 return 0;
233}
234
235/* ------------------------------------------------------------- */
236
237static inline void _put_byte(void **pp, u8 val)
238{
239 u8 *s = *pp;
240 *s++ = val;
241 *pp = s;
242}
243
244static inline void _put_word(void **pp, u32 val)
245{
246 u8 *s = *pp;
247 *s++ = val & 0xff;
248 *s++ = (val >> 8) & 0xff;
249 *s++ = (val >> 16) & 0xff;
250 *s++ = (val >> 24) & 0xff;
251 *pp = s;
252}
253
254static inline void _put_slice(void **pp, unsigned char *dp, unsigned int len)
255{
256 unsigned i = len;
257 _put_word(pp, i);
258 while (i-- > 0)
259 _put_byte(pp, *dp++);
260}
261
262static inline u8 _get_byte(void **pp)
263{
264 u8 *s = *pp;
265 u8 val;
266 val = *s++;
267 *pp = s;
268 return val;
269}
270
271static inline u32 _get_word(void **pp)
272{
273 u8 *s = *pp;
274 u32 val;
275 val = *s++;
276 val |= (*s++ << 8);
277 val |= (*s++ << 16);
278 val |= (*s++ << 24);
279 *pp = s;
280 return val;
281}
282
283static inline u32 _get_slice(void **pp, unsigned char *dp)
284{
285 unsigned int len, i;
286
287 len = i = _get_word(pp);
288 while (i-- > 0) *dp++ = _get_byte(pp);
289 return len;
290}
291
292/* ------------------------------------------------------------- */
293
294static void c4_reset(avmcard *card)
295{
296 unsigned long stop;
297
298 c4outmeml(card->mbase+DOORBELL, DBELL_RESET_ARM);
299
300 stop = jiffies + HZ*10;
301 while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) {
302 if (!time_before(jiffies, stop))
303 return;
304 c4outmeml(card->mbase+DOORBELL, DBELL_ADDR);
305 mb();
306 }
307
308 c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0);
309 c4_poke(card, DC21285_ARMCSR_BASE + CHAN_2_CONTROL, 0);
310}
311
312/* ------------------------------------------------------------- */
313
314static int c4_detect(avmcard *card)
315{
316 unsigned long stop, dummy;
317
318 c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c);
319 if (c4inmeml(card->mbase+PCI_OUT_INT_MASK) != 0x0c)
320 return 1;
321
322 c4outmeml(card->mbase+DOORBELL, DBELL_RESET_ARM);
323
324 stop = jiffies + HZ*10;
325 while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) {
326 if (!time_before(jiffies, stop))
327 return 2;
328 c4outmeml(card->mbase+DOORBELL, DBELL_ADDR);
329 mb();
330 }
331
332 c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0);
333 c4_poke(card, DC21285_ARMCSR_BASE + CHAN_2_CONTROL, 0);
334
335 c4outmeml(card->mbase+MAILBOX_0, 0x55aa55aa);
336 if (c4inmeml(card->mbase+MAILBOX_0) != 0x55aa55aa) return 3;
337
338 c4outmeml(card->mbase+MAILBOX_0, 0xaa55aa55);
339 if (c4inmeml(card->mbase+MAILBOX_0) != 0xaa55aa55) return 4;
340
341 if (c4_poke(card, DC21285_ARMCSR_BASE+DBELL_SA_MASK, 0)) return 5;
342 if (c4_poke(card, DC21285_ARMCSR_BASE+DBELL_PCI_MASK, 0)) return 6;
343 if (c4_poke(card, DC21285_ARMCSR_BASE+SA_CONTROL, SA_CTL_ALLRIGHT))
344 return 7;
345 if (c4_poke(card, DC21285_ARMCSR_BASE+XBUS_CYCLE, INIT_XBUS_CYCLE))
346 return 8;
347 if (c4_poke(card, DC21285_ARMCSR_BASE+XBUS_STROBE, INIT_XBUS_STROBE))
348 return 8;
349 if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, 0)) return 9;
350
351 mdelay(1);
352
353 if (c4_peek(card, DC21285_DRAM_A0MR, &dummy)) return 10;
354 if (c4_peek(card, DC21285_DRAM_A1MR, &dummy)) return 11;
355 if (c4_peek(card, DC21285_DRAM_A2MR, &dummy)) return 12;
356 if (c4_peek(card, DC21285_DRAM_A3MR, &dummy)) return 13;
357
358 if (c4_poke(card, DC21285_DRAM_A0MR+CAS_OFFSET, 0)) return 14;
359 if (c4_poke(card, DC21285_DRAM_A1MR+CAS_OFFSET, 0)) return 15;
360 if (c4_poke(card, DC21285_DRAM_A2MR+CAS_OFFSET, 0)) return 16;
361 if (c4_poke(card, DC21285_DRAM_A3MR+CAS_OFFSET, 0)) return 17;
362
363 mdelay(1);
364
365 if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, DRAM_TIMING_DEF))
366 return 18;
367
368 if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_0,DRAM_AD_SZ_DEF0))
369 return 19;
370 if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_1,DRAM_AD_SZ_NULL))
371 return 20;
372 if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_2,DRAM_AD_SZ_NULL))
373 return 21;
374 if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_3,DRAM_AD_SZ_NULL))
375 return 22;
376
377 /* Transputer test */
378
379 if ( c4_poke(card, 0x000000, 0x11111111)
380 || c4_poke(card, 0x400000, 0x22222222)
381 || c4_poke(card, 0x800000, 0x33333333)
382 || c4_poke(card, 0xC00000, 0x44444444))
383 return 23;
384
385 if ( c4_peek(card, 0x000000, &dummy) || dummy != 0x11111111
386 || c4_peek(card, 0x400000, &dummy) || dummy != 0x22222222
387 || c4_peek(card, 0x800000, &dummy) || dummy != 0x33333333
388 || c4_peek(card, 0xC00000, &dummy) || dummy != 0x44444444)
389 return 24;
390
391 if ( c4_poke(card, 0x000000, 0x55555555)
392 || c4_poke(card, 0x400000, 0x66666666)
393 || c4_poke(card, 0x800000, 0x77777777)
394 || c4_poke(card, 0xC00000, 0x88888888))
395 return 25;
396
397 if ( c4_peek(card, 0x000000, &dummy) || dummy != 0x55555555
398 || c4_peek(card, 0x400000, &dummy) || dummy != 0x66666666
399 || c4_peek(card, 0x800000, &dummy) || dummy != 0x77777777
400 || c4_peek(card, 0xC00000, &dummy) || dummy != 0x88888888)
401 return 26;
402
403 return 0;
404}
405
406/* ------------------------------------------------------------- */
407
408static void c4_dispatch_tx(avmcard *card)
409{
410 avmcard_dmainfo *dma = card->dma;
411 struct sk_buff *skb;
412 u8 cmd, subcmd;
413 u16 len;
414 u32 txlen;
415 void *p;
416
417
418 if (card->csr & DBELL_DOWN_ARM) { /* tx busy */
419 return;
420 }
421
422 skb = skb_dequeue(&dma->send_queue);
423 if (!skb) {
424#ifdef CONFIG_C4_DEBUG
425 printk(KERN_DEBUG "%s: tx underrun\n", card->name);
426#endif
427 return;
428 }
429
430 len = CAPIMSG_LEN(skb->data);
431
432 if (len) {
433 cmd = CAPIMSG_COMMAND(skb->data);
434 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
435
436 p = dma->sendbuf.dmabuf;
437
438 if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
439 u16 dlen = CAPIMSG_DATALEN(skb->data);
440 _put_byte(&p, SEND_DATA_B3_REQ);
441 _put_slice(&p, skb->data, len);
442 _put_slice(&p, skb->data + len, dlen);
443 } else {
444 _put_byte(&p, SEND_MESSAGE);
445 _put_slice(&p, skb->data, len);
446 }
447 txlen = (u8 *)p - (u8 *)dma->sendbuf.dmabuf;
448#ifdef CONFIG_C4_DEBUG
449 printk(KERN_DEBUG "%s: tx put msg len=%d\n", card->name, txlen);
450#endif
451 } else {
452 txlen = skb->len-2;
453#ifdef CONFIG_C4_POLLDEBUG
454 if (skb->data[2] == SEND_POLLACK)
455 printk(KERN_INFO "%s: ack to c4\n", card->name);
456#endif
457#ifdef CONFIG_C4_DEBUG
458 printk(KERN_DEBUG "%s: tx put 0x%x len=%d\n",
459 card->name, skb->data[2], txlen);
460#endif
461 memcpy(dma->sendbuf.dmabuf, skb->data+2, skb->len-2);
462 }
463 txlen = (txlen + 3) & ~3;
464
465 c4outmeml(card->mbase+MBOX_DOWN_ADDR, dma->sendbuf.dmaaddr);
466 c4outmeml(card->mbase+MBOX_DOWN_LEN, txlen);
467
468 card->csr |= DBELL_DOWN_ARM;
469
470 c4outmeml(card->mbase+DOORBELL, DBELL_DOWN_ARM);
471
472 dev_kfree_skb_any(skb);
473}
474
475/* ------------------------------------------------------------- */
476
477static void queue_pollack(avmcard *card)
478{
479 struct sk_buff *skb;
480 void *p;
481
482 skb = alloc_skb(3, GFP_ATOMIC);
483 if (!skb) {
484 printk(KERN_CRIT "%s: no memory, lost poll ack\n",
485 card->name);
486 return;
487 }
488 p = skb->data;
489 _put_byte(&p, 0);
490 _put_byte(&p, 0);
491 _put_byte(&p, SEND_POLLACK);
492 skb_put(skb, (u8 *)p - (u8 *)skb->data);
493
494 skb_queue_tail(&card->dma->send_queue, skb);
495 c4_dispatch_tx(card);
496}
497
498/* ------------------------------------------------------------- */
499
500static void c4_handle_rx(avmcard *card)
501{
502 avmcard_dmainfo *dma = card->dma;
503 struct capi_ctr *ctrl;
504 avmctrl_info *cinfo;
505 struct sk_buff *skb;
506 void *p = dma->recvbuf.dmabuf;
507 u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
508 u8 b1cmd = _get_byte(&p);
509 u32 cidx;
510
511
512#ifdef CONFIG_C4_DEBUG
513 printk(KERN_DEBUG "%s: rx 0x%x len=%lu\n", card->name,
514 b1cmd, (unsigned long)dma->recvlen);
515#endif
516
517 switch (b1cmd) {
518 case RECEIVE_DATA_B3_IND:
519
520 ApplId = (unsigned) _get_word(&p);
521 MsgLen = _get_slice(&p, card->msgbuf);
522 DataB3Len = _get_slice(&p, card->databuf);
523 cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr;
524 if (cidx >= card->nlogcontr) cidx = 0;
525 ctrl = &card->ctrlinfo[cidx].capi_ctrl;
526
527 if (MsgLen < 30) { /* not CAPI 64Bit */
528 memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
529 MsgLen = 30;
530 CAPIMSG_SETLEN(card->msgbuf, 30);
531 }
532 if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) {
533 printk(KERN_ERR "%s: incoming packet dropped\n",
534 card->name);
535 } else {
536 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
537 memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
538 capi_ctr_handle_message(ctrl, ApplId, skb);
539 }
540 break;
541
542 case RECEIVE_MESSAGE:
543
544 ApplId = (unsigned) _get_word(&p);
545 MsgLen = _get_slice(&p, card->msgbuf);
546 cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr;
547 if (cidx >= card->nlogcontr) cidx = 0;
548 cinfo = &card->ctrlinfo[cidx];
549 ctrl = &card->ctrlinfo[cidx].capi_ctrl;
550
551 if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
552 printk(KERN_ERR "%s: incoming packet dropped\n",
553 card->name);
554 } else {
555 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
556 if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF)
557 capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
558 CAPIMSG_NCCI(skb->data),
559 CAPIMSG_MSGID(skb->data));
560
561 capi_ctr_handle_message(ctrl, ApplId, skb);
562 }
563 break;
564
565 case RECEIVE_NEW_NCCI:
566
567 ApplId = _get_word(&p);
568 NCCI = _get_word(&p);
569 WindowSize = _get_word(&p);
570 cidx = (NCCI&0x7f) - card->cardnr;
571 if (cidx >= card->nlogcontr) cidx = 0;
572
573 capilib_new_ncci(&card->ctrlinfo[cidx].ncci_head, ApplId, NCCI, WindowSize);
574
575 break;
576
577 case RECEIVE_FREE_NCCI:
578
579 ApplId = _get_word(&p);
580 NCCI = _get_word(&p);
581
582 if (NCCI != 0xffffffff) {
583 cidx = (NCCI&0x7f) - card->cardnr;
584 if (cidx >= card->nlogcontr) cidx = 0;
585 capilib_free_ncci(&card->ctrlinfo[cidx].ncci_head, ApplId, NCCI);
586 }
587 break;
588
589 case RECEIVE_START:
590#ifdef CONFIG_C4_POLLDEBUG
591 printk(KERN_INFO "%s: poll from c4\n", card->name);
592#endif
593 if (!suppress_pollack)
594 queue_pollack(card);
595 for (cidx=0; cidx < card->nr_controllers; cidx++) {
596 ctrl = &card->ctrlinfo[cidx].capi_ctrl;
597 capi_ctr_resume_output(ctrl);
598 }
599 break;
600
601 case RECEIVE_STOP:
602 for (cidx=0; cidx < card->nr_controllers; cidx++) {
603 ctrl = &card->ctrlinfo[cidx].capi_ctrl;
604 capi_ctr_suspend_output(ctrl);
605 }
606 break;
607
608 case RECEIVE_INIT:
609
610 cidx = card->nlogcontr;
611 if (cidx >= card->nr_controllers) {
612 printk(KERN_ERR "%s: card with %d controllers ??\n",
613 card->name, cidx+1);
614 break;
615 }
616 card->nlogcontr++;
617 cinfo = &card->ctrlinfo[cidx];
618 ctrl = &cinfo->capi_ctrl;
619 cinfo->versionlen = _get_slice(&p, cinfo->versionbuf);
620 b1_parse_version(cinfo);
621 printk(KERN_INFO "%s: %s-card (%s) now active\n",
622 card->name,
623 cinfo->version[VER_CARDTYPE],
624 cinfo->version[VER_DRIVER]);
625 capi_ctr_ready(&cinfo->capi_ctrl);
626 break;
627
628 case RECEIVE_TASK_READY:
629 ApplId = (unsigned) _get_word(&p);
630 MsgLen = _get_slice(&p, card->msgbuf);
631 card->msgbuf[MsgLen] = 0;
632 while ( MsgLen > 0
633 && ( card->msgbuf[MsgLen-1] == '\n'
634 || card->msgbuf[MsgLen-1] == '\r')) {
635 card->msgbuf[MsgLen-1] = 0;
636 MsgLen--;
637 }
638 printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
639 card->name, ApplId, card->msgbuf);
640 break;
641
642 case RECEIVE_DEBUGMSG:
643 MsgLen = _get_slice(&p, card->msgbuf);
644 card->msgbuf[MsgLen] = 0;
645 while ( MsgLen > 0
646 && ( card->msgbuf[MsgLen-1] == '\n'
647 || card->msgbuf[MsgLen-1] == '\r')) {
648 card->msgbuf[MsgLen-1] = 0;
649 MsgLen--;
650 }
651 printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
652 break;
653
654 default:
655 printk(KERN_ERR "%s: c4_interrupt: 0x%x ???\n",
656 card->name, b1cmd);
657 return;
658 }
659}
660
661/* ------------------------------------------------------------- */
662
663static irqreturn_t c4_handle_interrupt(avmcard *card)
664{
665 unsigned long flags;
666 u32 status;
667
668 spin_lock_irqsave(&card->lock, flags);
669 status = c4inmeml(card->mbase+DOORBELL);
670
671 if (status & DBELL_RESET_HOST) {
672 u_int i;
673 c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c);
674 spin_unlock_irqrestore(&card->lock, flags);
675 if (card->nlogcontr == 0)
676 return IRQ_HANDLED;
677 printk(KERN_ERR "%s: unexpected reset\n", card->name);
678 for (i=0; i < card->nr_controllers; i++) {
679 avmctrl_info *cinfo = &card->ctrlinfo[i];
680 memset(cinfo->version, 0, sizeof(cinfo->version));
681 capilib_release(&cinfo->ncci_head);
682 capi_ctr_reseted(&cinfo->capi_ctrl);
683 }
684 card->nlogcontr = 0;
685 return IRQ_HANDLED;
686 }
687
688 status &= (DBELL_UP_HOST | DBELL_DOWN_HOST);
689 if (!status) {
690 spin_unlock_irqrestore(&card->lock, flags);
691 return IRQ_HANDLED;
692 }
693 c4outmeml(card->mbase+DOORBELL, status);
694
695 if ((status & DBELL_UP_HOST) != 0) {
696 card->dma->recvlen = c4inmeml(card->mbase+MBOX_UP_LEN);
697 c4outmeml(card->mbase+MBOX_UP_LEN, 0);
698 c4_handle_rx(card);
699 card->dma->recvlen = 0;
700 c4outmeml(card->mbase+MBOX_UP_LEN, card->dma->recvbuf.size);
701 c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
702 }
703
704 if ((status & DBELL_DOWN_HOST) != 0) {
705 card->csr &= ~DBELL_DOWN_ARM;
706 c4_dispatch_tx(card);
707 } else if (card->csr & DBELL_DOWN_HOST) {
708 if (c4inmeml(card->mbase+MBOX_DOWN_LEN) == 0) {
709 card->csr &= ~DBELL_DOWN_ARM;
710 c4_dispatch_tx(card);
711 }
712 }
713 spin_unlock_irqrestore(&card->lock, flags);
714 return IRQ_HANDLED;
715}
716
717static irqreturn_t c4_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
718{
719 avmcard *card = devptr;
720
721 return c4_handle_interrupt(card);
722}
723
724/* ------------------------------------------------------------- */
725
726static void c4_send_init(avmcard *card)
727{
728 struct sk_buff *skb;
729 void *p;
730
731 skb = alloc_skb(15, GFP_ATOMIC);
732 if (!skb) {
733 printk(KERN_CRIT "%s: no memory, lost register appl.\n",
734 card->name);
735 return;
736 }
737 p = skb->data;
738 _put_byte(&p, 0);
739 _put_byte(&p, 0);
740 _put_byte(&p, SEND_INIT);
741 _put_word(&p, CAPI_MAXAPPL);
742 _put_word(&p, AVM_NCCI_PER_CHANNEL*30);
743 _put_word(&p, card->cardnr - 1);
744 skb_put(skb, (u8 *)p - (u8 *)skb->data);
745
746 skb_queue_tail(&card->dma->send_queue, skb);
747 c4_dispatch_tx(card);
748}
749
750static int queue_sendconfigword(avmcard *card, u32 val)
751{
752 struct sk_buff *skb;
753 void *p;
754
755 skb = alloc_skb(3+4, GFP_ATOMIC);
756 if (!skb) {
757 printk(KERN_CRIT "%s: no memory, send config\n",
758 card->name);
759 return -ENOMEM;
760 }
761 p = skb->data;
762 _put_byte(&p, 0);
763 _put_byte(&p, 0);
764 _put_byte(&p, SEND_CONFIG);
765 _put_word(&p, val);
766 skb_put(skb, (u8 *)p - (u8 *)skb->data);
767
768 skb_queue_tail(&card->dma->send_queue, skb);
769 c4_dispatch_tx(card);
770 return 0;
771}
772
773static int queue_sendconfig(avmcard *card, char cval[4])
774{
775 struct sk_buff *skb;
776 unsigned long flags;
777 void *p;
778
779 skb = alloc_skb(3+4, GFP_ATOMIC);
780 if (!skb) {
781 printk(KERN_CRIT "%s: no memory, send config\n",
782 card->name);
783 return -ENOMEM;
784 }
785 p = skb->data;
786 _put_byte(&p, 0);
787 _put_byte(&p, 0);
788 _put_byte(&p, SEND_CONFIG);
789 _put_byte(&p, cval[0]);
790 _put_byte(&p, cval[1]);
791 _put_byte(&p, cval[2]);
792 _put_byte(&p, cval[3]);
793 skb_put(skb, (u8 *)p - (u8 *)skb->data);
794
795 skb_queue_tail(&card->dma->send_queue, skb);
796
797 spin_lock_irqsave(&card->lock, flags);
798 c4_dispatch_tx(card);
799 spin_unlock_irqrestore(&card->lock, flags);
800 return 0;
801}
802
803static int c4_send_config(avmcard *card, capiloaddatapart * config)
804{
805 u8 val[4];
806 unsigned char *dp;
807 u_int left;
808 int retval;
809
810 if ((retval = queue_sendconfigword(card, 1)) != 0)
811 return retval;
812 if ((retval = queue_sendconfigword(card, config->len)) != 0)
813 return retval;
814
815 dp = config->data;
816 left = config->len;
817 while (left >= sizeof(u32)) {
818 if (config->user) {
819 if (copy_from_user(val, dp, sizeof(val)))
820 return -EFAULT;
821 } else {
822 memcpy(val, dp, sizeof(val));
823 }
824 if ((retval = queue_sendconfig(card, val)) != 0)
825 return retval;
826 left -= sizeof(val);
827 dp += sizeof(val);
828 }
829 if (left) {
830 memset(val, 0, sizeof(val));
831 if (config->user) {
832 if (copy_from_user(&val, dp, left))
833 return -EFAULT;
834 } else {
835 memcpy(&val, dp, left);
836 }
837 if ((retval = queue_sendconfig(card, val)) != 0)
838 return retval;
839 }
840
841 return 0;
842}
843
844static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
845{
846 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
847 avmcard *card = cinfo->card;
848 int retval;
849
850 if ((retval = c4_load_t4file(card, &data->firmware))) {
851 printk(KERN_ERR "%s: failed to load t4file!!\n",
852 card->name);
853 c4_reset(card);
854 return retval;
855 }
856
857 card->csr = 0;
858 c4outmeml(card->mbase+MBOX_UP_LEN, 0);
859 c4outmeml(card->mbase+MBOX_DOWN_LEN, 0);
860 c4outmeml(card->mbase+DOORBELL, DBELL_INIT);
861 mdelay(1);
862 c4outmeml(card->mbase+DOORBELL,
863 DBELL_UP_HOST | DBELL_DOWN_HOST | DBELL_RESET_HOST);
864
865 c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x08);
866
867 card->dma->recvlen = 0;
868 c4outmeml(card->mbase+MBOX_UP_ADDR, card->dma->recvbuf.dmaaddr);
869 c4outmeml(card->mbase+MBOX_UP_LEN, card->dma->recvbuf.size);
870 c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
871
872 if (data->configuration.len > 0 && data->configuration.data) {
873 retval = c4_send_config(card, &data->configuration);
874 if (retval) {
875 printk(KERN_ERR "%s: failed to set config!!\n",
876 card->name);
877 c4_reset(card);
878 return retval;
879 }
880 }
881
882 c4_send_init(card);
883
884 return 0;
885}
886
887
888void c4_reset_ctr(struct capi_ctr *ctrl)
889{
890 avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card;
891 avmctrl_info *cinfo;
892 u_int i;
893 unsigned long flags;
894
895 spin_lock_irqsave(&card->lock, flags);
896
897 c4_reset(card);
898
899 spin_unlock_irqrestore(&card->lock, flags);
900
901 for (i=0; i < card->nr_controllers; i++) {
902 cinfo = &card->ctrlinfo[i];
903 memset(cinfo->version, 0, sizeof(cinfo->version));
904 capi_ctr_reseted(&cinfo->capi_ctrl);
905 }
906 card->nlogcontr = 0;
907}
908
909static void c4_remove(struct pci_dev *pdev)
910{
911 avmcard *card = pci_get_drvdata(pdev);
912 avmctrl_info *cinfo;
913 u_int i;
914
915 if (!card)
916 return;
917
918 c4_reset(card);
919
920 for (i=0; i < card->nr_controllers; i++) {
921 cinfo = &card->ctrlinfo[i];
922 detach_capi_ctr(&cinfo->capi_ctrl);
923 }
924
925 free_irq(card->irq, card);
926 iounmap(card->mbase);
927 release_region(card->port, AVMB1_PORTLEN);
928 avmcard_dma_free(card->dma);
929 pci_set_drvdata(pdev, NULL);
930 b1_free_card(card);
931}
932
933/* ------------------------------------------------------------- */
934
935
936void c4_register_appl(struct capi_ctr *ctrl,
937 u16 appl,
938 capi_register_params *rp)
939{
940 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
941 avmcard *card = cinfo->card;
942 struct sk_buff *skb;
943 int want = rp->level3cnt;
944 unsigned long flags;
945 int nconn;
946 void *p;
947
948 if (ctrl->cnr == card->cardnr) {
949
950 if (want > 0) nconn = want;
951 else nconn = ctrl->profile.nbchannel * 4 * -want;
952 if (nconn == 0) nconn = ctrl->profile.nbchannel * 4;
953
954 skb = alloc_skb(23, GFP_ATOMIC);
955 if (!skb) {
956 printk(KERN_CRIT "%s: no memory, lost register appl.\n",
957 card->name);
958 return;
959 }
960 p = skb->data;
961 _put_byte(&p, 0);
962 _put_byte(&p, 0);
963 _put_byte(&p, SEND_REGISTER);
964 _put_word(&p, appl);
965 _put_word(&p, 1024 * (nconn+1));
966 _put_word(&p, nconn);
967 _put_word(&p, rp->datablkcnt);
968 _put_word(&p, rp->datablklen);
969 skb_put(skb, (u8 *)p - (u8 *)skb->data);
970
971 skb_queue_tail(&card->dma->send_queue, skb);
972
973 spin_lock_irqsave(&card->lock, flags);
974 c4_dispatch_tx(card);
975 spin_unlock_irqrestore(&card->lock, flags);
976 }
977}
978
979/* ------------------------------------------------------------- */
980
981void c4_release_appl(struct capi_ctr *ctrl, u16 appl)
982{
983 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
984 avmcard *card = cinfo->card;
985 unsigned long flags;
986 struct sk_buff *skb;
987 void *p;
988
989 capilib_release_appl(&cinfo->ncci_head, appl);
990
991 if (ctrl->cnr == card->cardnr) {
992 skb = alloc_skb(7, GFP_ATOMIC);
993 if (!skb) {
994 printk(KERN_CRIT "%s: no memory, lost release appl.\n",
995 card->name);
996 return;
997 }
998 p = skb->data;
999 _put_byte(&p, 0);
1000 _put_byte(&p, 0);
1001 _put_byte(&p, SEND_RELEASE);
1002 _put_word(&p, appl);
1003
1004 skb_put(skb, (u8 *)p - (u8 *)skb->data);
1005 skb_queue_tail(&card->dma->send_queue, skb);
1006 spin_lock_irqsave(&card->lock, flags);
1007 c4_dispatch_tx(card);
1008 spin_unlock_irqrestore(&card->lock, flags);
1009 }
1010}
1011
1012/* ------------------------------------------------------------- */
1013
1014
1015static u16 c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
1016{
1017 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
1018 avmcard *card = cinfo->card;
1019 u16 retval = CAPI_NOERROR;
1020 unsigned long flags;
1021
1022 if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
1023 retval = capilib_data_b3_req(&cinfo->ncci_head,
1024 CAPIMSG_APPID(skb->data),
1025 CAPIMSG_NCCI(skb->data),
1026 CAPIMSG_MSGID(skb->data));
1027 }
1028 if (retval == CAPI_NOERROR) {
1029 skb_queue_tail(&card->dma->send_queue, skb);
1030 spin_lock_irqsave(&card->lock, flags);
1031 c4_dispatch_tx(card);
1032 spin_unlock_irqrestore(&card->lock, flags);
1033 }
1034 return retval;
1035}
1036
1037/* ------------------------------------------------------------- */
1038
1039static char *c4_procinfo(struct capi_ctr *ctrl)
1040{
1041 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
1042
1043 if (!cinfo)
1044 return "";
1045 sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx",
1046 cinfo->cardname[0] ? cinfo->cardname : "-",
1047 cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
1048 cinfo->card ? cinfo->card->port : 0x0,
1049 cinfo->card ? cinfo->card->irq : 0,
1050 cinfo->card ? cinfo->card->membase : 0
1051 );
1052 return cinfo->infobuf;
1053}
1054
1055static int c4_read_proc(char *page, char **start, off_t off,
1056 int count, int *eof, struct capi_ctr *ctrl)
1057{
1058 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
1059 avmcard *card = cinfo->card;
1060 u8 flag;
1061 int len = 0;
1062 char *s;
1063
1064 len += sprintf(page+len, "%-16s %s\n", "name", card->name);
1065 len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
1066 len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
1067 len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase);
1068 switch (card->cardtype) {
1069 case avm_b1isa: s = "B1 ISA"; break;
1070 case avm_b1pci: s = "B1 PCI"; break;
1071 case avm_b1pcmcia: s = "B1 PCMCIA"; break;
1072 case avm_m1: s = "M1"; break;
1073 case avm_m2: s = "M2"; break;
1074 case avm_t1isa: s = "T1 ISA (HEMA)"; break;
1075 case avm_t1pci: s = "T1 PCI"; break;
1076 case avm_c4: s = "C4"; break;
1077 case avm_c2: s = "C2"; break;
1078 default: s = "???"; break;
1079 }
1080 len += sprintf(page+len, "%-16s %s\n", "type", s);
1081 if ((s = cinfo->version[VER_DRIVER]) != 0)
1082 len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
1083 if ((s = cinfo->version[VER_CARDTYPE]) != 0)
1084 len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
1085 if ((s = cinfo->version[VER_SERIAL]) != 0)
1086 len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
1087
1088 if (card->cardtype != avm_m1) {
1089 flag = ((u8 *)(ctrl->profile.manu))[3];
1090 if (flag)
1091 len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n",
1092 "protocol",
1093 (flag & 0x01) ? " DSS1" : "",
1094 (flag & 0x02) ? " CT1" : "",
1095 (flag & 0x04) ? " VN3" : "",
1096 (flag & 0x08) ? " NI1" : "",
1097 (flag & 0x10) ? " AUSTEL" : "",
1098 (flag & 0x20) ? " ESS" : "",
1099 (flag & 0x40) ? " 1TR6" : ""
1100 );
1101 }
1102 if (card->cardtype != avm_m1) {
1103 flag = ((u8 *)(ctrl->profile.manu))[5];
1104 if (flag)
1105 len += sprintf(page+len, "%-16s%s%s%s%s\n",
1106 "linetype",
1107 (flag & 0x01) ? " point to point" : "",
1108 (flag & 0x02) ? " point to multipoint" : "",
1109 (flag & 0x08) ? " leased line without D-channel" : "",
1110 (flag & 0x04) ? " leased line with D-channel" : ""
1111 );
1112 }
1113 len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
1114
1115 if (off+count >= len)
1116 *eof = 1;
1117 if (len < off)
1118 return 0;
1119 *start = page + off;
1120 return ((count < len-off) ? count : len-off);
1121}
1122
1123/* ------------------------------------------------------------- */
1124
1125static int c4_add_card(struct capicardparams *p, struct pci_dev *dev,
1126 int nr_controllers)
1127{
1128 avmcard *card;
1129 avmctrl_info *cinfo;
1130 int retval;
1131 int i;
1132
1133 card = b1_alloc_card(nr_controllers);
1134 if (!card) {
1135 printk(KERN_WARNING "c4: no memory.\n");
1136 retval = -ENOMEM;
1137 goto err;
1138 }
1139 card->dma = avmcard_dma_alloc("c4", dev, 2048+128, 2048+128);
1140 if (!card->dma) {
1141 printk(KERN_WARNING "c4: no memory.\n");
1142 retval = -ENOMEM;
1143 goto err_free;
1144 }
1145
1146 sprintf(card->name, "c%d-%x", nr_controllers, p->port);
1147 card->port = p->port;
1148 card->irq = p->irq;
1149 card->membase = p->membase;
1150 card->cardtype = (nr_controllers == 4) ? avm_c4 : avm_c2;
1151
1152 if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
1153 printk(KERN_WARNING "c4: ports 0x%03x-0x%03x in use.\n",
1154 card->port, card->port + AVMB1_PORTLEN);
1155 retval = -EBUSY;
1156 goto err_free_dma;
1157 }
1158
1159 card->mbase = ioremap(card->membase, 128);
1160 if (card->mbase == 0) {
1161 printk(KERN_NOTICE "c4: can't remap memory at 0x%lx\n",
1162 card->membase);
1163 retval = -EIO;
1164 goto err_release_region;
1165 }
1166
1167 retval = c4_detect(card);
1168 if (retval != 0) {
1169 printk(KERN_NOTICE "c4: NO card at 0x%x error(%d)\n",
1170 card->port, retval);
1171 retval = -EIO;
1172 goto err_unmap;
1173 }
1174 c4_reset(card);
1175
1176 retval = request_irq(card->irq, c4_interrupt, SA_SHIRQ, card->name, card);
1177 if (retval) {
1178 printk(KERN_ERR "c4: unable to get IRQ %d.\n",card->irq);
1179 retval = -EBUSY;
1180 goto err_unmap;
1181 }
1182
1183 for (i=0; i < nr_controllers ; i++) {
1184 cinfo = &card->ctrlinfo[i];
1185 cinfo->capi_ctrl.owner = THIS_MODULE;
1186 cinfo->capi_ctrl.driver_name = "c4";
1187 cinfo->capi_ctrl.driverdata = cinfo;
1188 cinfo->capi_ctrl.register_appl = c4_register_appl;
1189 cinfo->capi_ctrl.release_appl = c4_release_appl;
1190 cinfo->capi_ctrl.send_message = c4_send_message;
1191 cinfo->capi_ctrl.load_firmware = c4_load_firmware;
1192 cinfo->capi_ctrl.reset_ctr = c4_reset_ctr;
1193 cinfo->capi_ctrl.procinfo = c4_procinfo;
1194 cinfo->capi_ctrl.ctr_read_proc = c4_read_proc;
1195 strcpy(cinfo->capi_ctrl.name, card->name);
1196
1197 retval = attach_capi_ctr(&cinfo->capi_ctrl);
1198 if (retval) {
1199 printk(KERN_ERR "c4: attach controller failed (%d).\n", i);
1200 for (i--; i >= 0; i--) {
1201 cinfo = &card->ctrlinfo[i];
1202 detach_capi_ctr(&cinfo->capi_ctrl);
1203 }
1204 goto err_free_irq;
1205 }
1206 if (i == 0)
1207 card->cardnr = cinfo->capi_ctrl.cnr;
1208 }
1209
1210 printk(KERN_INFO "c4: AVM C%d at i/o %#x, irq %d, mem %#lx\n",
1211 nr_controllers, card->port, card->irq,
1212 card->membase);
1213 pci_set_drvdata(dev, card);
1214 return 0;
1215
1216 err_free_irq:
1217 free_irq(card->irq, card);
1218 err_unmap:
1219 iounmap(card->mbase);
1220 err_release_region:
1221 release_region(card->port, AVMB1_PORTLEN);
1222 err_free_dma:
1223 avmcard_dma_free(card->dma);
1224 err_free:
1225 b1_free_card(card);
1226 err:
1227 return retval;
1228}
1229
1230/* ------------------------------------------------------------- */
1231
1232static int __devinit c4_probe(struct pci_dev *dev,
1233 const struct pci_device_id *ent)
1234{
1235 int nr = ent->driver_data;
1236 int retval = 0;
1237 struct capicardparams param;
1238
1239 if (pci_enable_device(dev) < 0) {
1240 printk(KERN_ERR "c4: failed to enable AVM-C%d\n", nr);
1241 return -ENODEV;
1242 }
1243 pci_set_master(dev);
1244
1245 param.port = pci_resource_start(dev, 1);
1246 param.irq = dev->irq;
1247 param.membase = pci_resource_start(dev, 0);
1248
1249 printk(KERN_INFO "c4: PCI BIOS reports AVM-C%d at i/o %#x, irq %d, mem %#x\n",
1250 nr, param.port, param.irq, param.membase);
1251
1252 retval = c4_add_card(&param, dev, nr);
1253 if (retval != 0) {
1254 printk(KERN_ERR "c4: no AVM-C%d at i/o %#x, irq %d detected, mem %#x\n",
1255 nr, param.port, param.irq, param.membase);
1256 return -ENODEV;
1257 }
1258 return 0;
1259}
1260
1261static struct pci_driver c4_pci_driver = {
1262 .name = "c4",
1263 .id_table = c4_pci_tbl,
1264 .probe = c4_probe,
1265 .remove = c4_remove,
1266};
1267
1268static struct capi_driver capi_driver_c2 = {
1269 .name = "c2",
1270 .revision = "1.0",
1271};
1272
1273static struct capi_driver capi_driver_c4 = {
1274 .name = "c4",
1275 .revision = "1.0",
1276};
1277
1278static int __init c4_init(void)
1279{
1280 char *p;
1281 char rev[32];
1282 int err;
1283
1284 if ((p = strchr(revision, ':')) != 0 && p[1]) {
1285 strlcpy(rev, p + 2, 32);
1286 if ((p = strchr(rev, '$')) != 0 && p > rev)
1287 *(p-1) = 0;
1288 } else
1289 strcpy(rev, "1.0");
1290
1291 err = pci_register_driver(&c4_pci_driver);
1292 if (!err) {
1293 strlcpy(capi_driver_c2.revision, rev, 32);
1294 register_capi_driver(&capi_driver_c2);
1295 strlcpy(capi_driver_c4.revision, rev, 32);
1296 register_capi_driver(&capi_driver_c4);
1297 printk(KERN_INFO "c4: revision %s\n", rev);
1298 }
1299 return err;
1300}
1301
1302static void __exit c4_exit(void)
1303{
1304 unregister_capi_driver(&capi_driver_c2);
1305 unregister_capi_driver(&capi_driver_c4);
1306 pci_unregister_driver(&c4_pci_driver);
1307}
1308
1309module_init(c4_init);
1310module_exit(c4_exit);
diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c
new file mode 100644
index 000000000000..cb9d9cee2a64
--- /dev/null
+++ b/drivers/isdn/hardware/avm/t1isa.c
@@ -0,0 +1,596 @@
1/* $Id: t1isa.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $
2 *
3 * Module for AVM T1 HEMA-card.
4 *
5 * Copyright 1999 by Carsten Paeth <calle@calle.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/skbuff.h>
15#include <linux/delay.h>
16#include <linux/mm.h>
17#include <linux/interrupt.h>
18#include <linux/ioport.h>
19#include <linux/capi.h>
20#include <linux/netdevice.h>
21#include <linux/kernelcapi.h>
22#include <linux/init.h>
23#include <linux/pci.h>
24#include <asm/io.h>
25#include <linux/isdn/capicmd.h>
26#include <linux/isdn/capiutil.h>
27#include <linux/isdn/capilli.h>
28#include "avmcard.h"
29
30/* ------------------------------------------------------------- */
31
32static char *revision = "$Revision: 1.1.2.3 $";
33
34/* ------------------------------------------------------------- */
35
36MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 HEMA ISA card");
37MODULE_AUTHOR("Carsten Paeth");
38MODULE_LICENSE("GPL");
39
40/* ------------------------------------------------------------- */
41
42static int hema_irq_table[16] =
43{0,
44 0,
45 0,
46 0x80, /* irq 3 */
47 0,
48 0x90, /* irq 5 */
49 0,
50 0xA0, /* irq 7 */
51 0,
52 0xB0, /* irq 9 */
53 0xC0, /* irq 10 */
54 0xD0, /* irq 11 */
55 0xE0, /* irq 12 */
56 0,
57 0,
58 0xF0, /* irq 15 */
59};
60
61static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr)
62{
63 unsigned char cregs[8];
64 unsigned char reverse_cardnr;
65 unsigned char dummy;
66 int i;
67
68 reverse_cardnr = ((cardnr & 0x01) << 3) | ((cardnr & 0x02) << 1)
69 | ((cardnr & 0x04) >> 1) | ((cardnr & 0x08) >> 3);
70 cregs[0] = (HEMA_VERSION_ID << 4) | (reverse_cardnr & 0xf);
71 cregs[1] = 0x00; /* fast & slow link connected to CON1 */
72 cregs[2] = 0x05; /* fast link 20MBit, slow link 20 MBit */
73 cregs[3] = 0;
74 cregs[4] = 0x11; /* zero wait state */
75 cregs[5] = hema_irq_table[irq & 0xf];
76 cregs[6] = 0;
77 cregs[7] = 0;
78
79 /*
80 * no one else should use the ISA bus in this moment,
81 * but no function there to prevent this :-(
82 * save_flags(flags); cli();
83 */
84
85 /* board reset */
86 t1outp(base, T1_RESETBOARD, 0xf);
87 mdelay(100);
88 dummy = t1inp(base, T1_FASTLINK+T1_OUTSTAT); /* first read */
89
90 /* write config */
91 dummy = (base >> 4) & 0xff;
92 for (i=1;i<=0xf;i++) t1outp(base, i, dummy);
93 t1outp(base, HEMA_PAL_ID & 0xf, dummy);
94 t1outp(base, HEMA_PAL_ID >> 4, cregs[0]);
95 for(i=1;i<7;i++) t1outp(base, 0, cregs[i]);
96 t1outp(base, ((base >> 4)) & 0x3, cregs[7]);
97 /* restore_flags(flags); */
98
99 mdelay(100);
100 t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
101 t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
102 mdelay(10);
103 t1outp(base, T1_FASTLINK+T1_RESETLINK, 1);
104 t1outp(base, T1_SLOWLINK+T1_RESETLINK, 1);
105 mdelay(100);
106 t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
107 t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
108 mdelay(10);
109 t1outp(base, T1_FASTLINK+T1_ANALYSE, 0);
110 mdelay(5);
111 t1outp(base, T1_SLOWLINK+T1_ANALYSE, 0);
112
113 if (t1inp(base, T1_FASTLINK+T1_OUTSTAT) != 0x1) /* tx empty */
114 return 1;
115 if (t1inp(base, T1_FASTLINK+T1_INSTAT) != 0x0) /* rx empty */
116 return 2;
117 if (t1inp(base, T1_FASTLINK+T1_IRQENABLE) != 0x0)
118 return 3;
119 if ((t1inp(base, T1_FASTLINK+T1_FIFOSTAT) & 0xf0) != 0x70)
120 return 4;
121 if ((t1inp(base, T1_FASTLINK+T1_IRQMASTER) & 0x0e) != 0)
122 return 5;
123 if ((t1inp(base, T1_FASTLINK+T1_IDENT) & 0x7d) != 1)
124 return 6;
125 if (t1inp(base, T1_SLOWLINK+T1_OUTSTAT) != 0x1) /* tx empty */
126 return 7;
127 if ((t1inp(base, T1_SLOWLINK+T1_IRQMASTER) & 0x0e) != 0)
128 return 8;
129 if ((t1inp(base, T1_SLOWLINK+T1_IDENT) & 0x7d) != 0)
130 return 9;
131 return 0;
132}
133
134static irqreturn_t t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
135{
136 avmcard *card = devptr;
137 avmctrl_info *cinfo = &card->ctrlinfo[0];
138 struct capi_ctr *ctrl = &cinfo->capi_ctrl;
139 unsigned char b1cmd;
140 struct sk_buff *skb;
141
142 unsigned ApplId;
143 unsigned MsgLen;
144 unsigned DataB3Len;
145 unsigned NCCI;
146 unsigned WindowSize;
147 unsigned long flags;
148
149 spin_lock_irqsave(&card->lock, flags);
150
151 while (b1_rx_full(card->port)) {
152
153 b1cmd = b1_get_byte(card->port);
154
155 switch (b1cmd) {
156
157 case RECEIVE_DATA_B3_IND:
158
159 ApplId = (unsigned) b1_get_word(card->port);
160 MsgLen = t1_get_slice(card->port, card->msgbuf);
161 DataB3Len = t1_get_slice(card->port, card->databuf);
162 spin_unlock_irqrestore(&card->lock, flags);
163
164 if (MsgLen < 30) { /* not CAPI 64Bit */
165 memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
166 MsgLen = 30;
167 CAPIMSG_SETLEN(card->msgbuf, 30);
168 }
169 if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) {
170 printk(KERN_ERR "%s: incoming packet dropped\n",
171 card->name);
172 } else {
173 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
174 memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
175 capi_ctr_handle_message(ctrl, ApplId, skb);
176 }
177 break;
178
179 case RECEIVE_MESSAGE:
180
181 ApplId = (unsigned) b1_get_word(card->port);
182 MsgLen = t1_get_slice(card->port, card->msgbuf);
183 spin_unlock_irqrestore(&card->lock, flags);
184 if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
185 printk(KERN_ERR "%s: incoming packet dropped\n",
186 card->name);
187 } else {
188 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
189 if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3)
190 capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
191 CAPIMSG_NCCI(skb->data),
192 CAPIMSG_MSGID(skb->data));
193
194 capi_ctr_handle_message(ctrl, ApplId, skb);
195 }
196 break;
197
198 case RECEIVE_NEW_NCCI:
199
200 ApplId = b1_get_word(card->port);
201 NCCI = b1_get_word(card->port);
202 WindowSize = b1_get_word(card->port);
203 spin_unlock_irqrestore(&card->lock, flags);
204
205 capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
206
207 break;
208
209 case RECEIVE_FREE_NCCI:
210
211 ApplId = b1_get_word(card->port);
212 NCCI = b1_get_word(card->port);
213 spin_unlock_irqrestore(&card->lock, flags);
214
215 if (NCCI != 0xffffffff)
216 capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
217
218 break;
219
220 case RECEIVE_START:
221 b1_put_byte(card->port, SEND_POLLACK);
222 spin_unlock_irqrestore(&card->lock, flags);
223 capi_ctr_resume_output(ctrl);
224 break;
225
226 case RECEIVE_STOP:
227 spin_unlock_irqrestore(&card->lock, flags);
228 capi_ctr_suspend_output(ctrl);
229 break;
230
231 case RECEIVE_INIT:
232
233 cinfo->versionlen = t1_get_slice(card->port, cinfo->versionbuf);
234 spin_unlock_irqrestore(&card->lock, flags);
235 b1_parse_version(cinfo);
236 printk(KERN_INFO "%s: %s-card (%s) now active\n",
237 card->name,
238 cinfo->version[VER_CARDTYPE],
239 cinfo->version[VER_DRIVER]);
240 capi_ctr_ready(ctrl);
241 break;
242
243 case RECEIVE_TASK_READY:
244 ApplId = (unsigned) b1_get_word(card->port);
245 MsgLen = t1_get_slice(card->port, card->msgbuf);
246 spin_unlock_irqrestore(&card->lock, flags);
247 card->msgbuf[MsgLen] = 0;
248 while ( MsgLen > 0
249 && ( card->msgbuf[MsgLen-1] == '\n'
250 || card->msgbuf[MsgLen-1] == '\r')) {
251 card->msgbuf[MsgLen-1] = 0;
252 MsgLen--;
253 }
254 printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
255 card->name, ApplId, card->msgbuf);
256 break;
257
258 case RECEIVE_DEBUGMSG:
259 MsgLen = t1_get_slice(card->port, card->msgbuf);
260 spin_unlock_irqrestore(&card->lock, flags);
261 card->msgbuf[MsgLen] = 0;
262 while ( MsgLen > 0
263 && ( card->msgbuf[MsgLen-1] == '\n'
264 || card->msgbuf[MsgLen-1] == '\r')) {
265 card->msgbuf[MsgLen-1] = 0;
266 MsgLen--;
267 }
268 printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
269 break;
270
271
272 case 0xff:
273 spin_unlock_irqrestore(&card->lock, flags);
274 printk(KERN_ERR "%s: card reseted ?\n", card->name);
275 return IRQ_HANDLED;
276 default:
277 spin_unlock_irqrestore(&card->lock, flags);
278 printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n",
279 card->name, b1cmd);
280 return IRQ_NONE;
281 }
282 }
283 return IRQ_HANDLED;
284}
285
286/* ------------------------------------------------------------- */
287
288static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
289{
290 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
291 avmcard *card = cinfo->card;
292 unsigned int port = card->port;
293 unsigned long flags;
294 int retval;
295
296 t1_disable_irq(port);
297 b1_reset(port);
298
299 if ((retval = b1_load_t4file(card, &data->firmware))) {
300 b1_reset(port);
301 printk(KERN_ERR "%s: failed to load t4file!!\n",
302 card->name);
303 return retval;
304 }
305
306 if (data->configuration.len > 0 && data->configuration.data) {
307 if ((retval = b1_load_config(card, &data->configuration))) {
308 b1_reset(port);
309 printk(KERN_ERR "%s: failed to load config!!\n",
310 card->name);
311 return retval;
312 }
313 }
314
315 if (!b1_loaded(card)) {
316 printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
317 return -EIO;
318 }
319
320 spin_lock_irqsave(&card->lock, flags);
321 b1_setinterrupt(port, card->irq, card->cardtype);
322 b1_put_byte(port, SEND_INIT);
323 b1_put_word(port, CAPI_MAXAPPL);
324 b1_put_word(port, AVM_NCCI_PER_CHANNEL*30);
325 b1_put_word(port, ctrl->cnr - 1);
326 spin_unlock_irqrestore(&card->lock, flags);
327
328 return 0;
329}
330
331void t1isa_reset_ctr(struct capi_ctr *ctrl)
332{
333 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
334 avmcard *card = cinfo->card;
335 unsigned int port = card->port;
336
337 t1_disable_irq(port);
338 b1_reset(port);
339 b1_reset(port);
340
341 memset(cinfo->version, 0, sizeof(cinfo->version));
342 capilib_release(&cinfo->ncci_head);
343 capi_ctr_reseted(ctrl);
344}
345
346static void t1isa_remove(struct pci_dev *pdev)
347{
348 avmctrl_info *cinfo = pci_get_drvdata(pdev);
349 avmcard *card;
350
351 if (!cinfo)
352 return;
353
354 card = cinfo->card;
355
356 t1_disable_irq(card->port);
357 b1_reset(card->port);
358 b1_reset(card->port);
359 t1_reset(card->port);
360
361 detach_capi_ctr(&cinfo->capi_ctrl);
362 free_irq(card->irq, card);
363 release_region(card->port, AVMB1_PORTLEN);
364 b1_free_card(card);
365}
366
367/* ------------------------------------------------------------- */
368
369static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
370static char *t1isa_procinfo(struct capi_ctr *ctrl);
371
372static int t1isa_probe(struct pci_dev *pdev, int cardnr)
373{
374 avmctrl_info *cinfo;
375 avmcard *card;
376 int retval;
377
378 card = b1_alloc_card(1);
379 if (!card) {
380 printk(KERN_WARNING "t1isa: no memory.\n");
381 retval = -ENOMEM;
382 goto err;
383 }
384
385 cinfo = card->ctrlinfo;
386 card->port = pci_resource_start(pdev, 0);
387 card->irq = pdev->irq;
388 card->cardtype = avm_t1isa;
389 card->cardnr = cardnr;
390 sprintf(card->name, "t1isa-%x", card->port);
391
392 if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) {
393 printk(KERN_WARNING "t1isa: invalid port 0x%x.\n", card->port);
394 retval = -EINVAL;
395 goto err_free;
396 }
397 if (hema_irq_table[card->irq & 0xf] == 0) {
398 printk(KERN_WARNING "t1isa: irq %d not valid.\n", card->irq);
399 retval = -EINVAL;
400 goto err_free;
401 }
402 if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
403 printk(KERN_INFO "t1isa: ports 0x%03x-0x%03x in use.\n",
404 card->port, card->port + AVMB1_PORTLEN);
405 retval = -EBUSY;
406 goto err_free;
407 }
408 retval = request_irq(card->irq, t1isa_interrupt, 0, card->name, card);
409 if (retval) {
410 printk(KERN_INFO "t1isa: unable to get IRQ %d.\n", card->irq);
411 retval = -EBUSY;
412 goto err_release_region;
413 }
414
415 if ((retval = t1_detectandinit(card->port, card->irq, card->cardnr)) != 0) {
416 printk(KERN_INFO "t1isa: NO card at 0x%x (%d)\n",
417 card->port, retval);
418 retval = -ENODEV;
419 goto err_free_irq;
420 }
421 t1_disable_irq(card->port);
422 b1_reset(card->port);
423
424 cinfo->capi_ctrl.owner = THIS_MODULE;
425 cinfo->capi_ctrl.driver_name = "t1isa";
426 cinfo->capi_ctrl.driverdata = cinfo;
427 cinfo->capi_ctrl.register_appl = b1_register_appl;
428 cinfo->capi_ctrl.release_appl = b1_release_appl;
429 cinfo->capi_ctrl.send_message = t1isa_send_message;
430 cinfo->capi_ctrl.load_firmware = t1isa_load_firmware;
431 cinfo->capi_ctrl.reset_ctr = t1isa_reset_ctr;
432 cinfo->capi_ctrl.procinfo = t1isa_procinfo;
433 cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc;
434 strcpy(cinfo->capi_ctrl.name, card->name);
435
436 retval = attach_capi_ctr(&cinfo->capi_ctrl);
437 if (retval) {
438 printk(KERN_INFO "t1isa: attach controller failed.\n");
439 goto err_free_irq;
440 }
441
442 printk(KERN_INFO "t1isa: AVM T1 ISA at i/o %#x, irq %d, card %d\n",
443 card->port, card->irq, card->cardnr);
444
445 pci_set_drvdata(pdev, cinfo);
446 return 0;
447
448 err_free_irq:
449 free_irq(card->irq, card);
450 err_release_region:
451 release_region(card->port, AVMB1_PORTLEN);
452 err_free:
453 b1_free_card(card);
454 err:
455 return retval;
456}
457
458static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
459{
460 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
461 avmcard *card = cinfo->card;
462 unsigned int port = card->port;
463 unsigned long flags;
464 u16 len = CAPIMSG_LEN(skb->data);
465 u8 cmd = CAPIMSG_COMMAND(skb->data);
466 u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
467 u16 dlen, retval;
468
469 if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
470 retval = capilib_data_b3_req(&cinfo->ncci_head,
471 CAPIMSG_APPID(skb->data),
472 CAPIMSG_NCCI(skb->data),
473 CAPIMSG_MSGID(skb->data));
474 if (retval != CAPI_NOERROR)
475 return retval;
476
477 dlen = CAPIMSG_DATALEN(skb->data);
478
479 spin_lock_irqsave(&card->lock, flags);
480 b1_put_byte(port, SEND_DATA_B3_REQ);
481 t1_put_slice(port, skb->data, len);
482 t1_put_slice(port, skb->data + len, dlen);
483 spin_unlock_irqrestore(&card->lock, flags);
484 } else {
485
486 spin_lock_irqsave(&card->lock, flags);
487 b1_put_byte(port, SEND_MESSAGE);
488 t1_put_slice(port, skb->data, len);
489 spin_unlock_irqrestore(&card->lock, flags);
490 }
491
492 dev_kfree_skb_any(skb);
493 return CAPI_NOERROR;
494}
495/* ------------------------------------------------------------- */
496
497static char *t1isa_procinfo(struct capi_ctr *ctrl)
498{
499 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
500
501 if (!cinfo)
502 return "";
503 sprintf(cinfo->infobuf, "%s %s 0x%x %d %d",
504 cinfo->cardname[0] ? cinfo->cardname : "-",
505 cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
506 cinfo->card ? cinfo->card->port : 0x0,
507 cinfo->card ? cinfo->card->irq : 0,
508 cinfo->card ? cinfo->card->cardnr : 0
509 );
510 return cinfo->infobuf;
511}
512
513
514/* ------------------------------------------------------------- */
515
516#define MAX_CARDS 4
517static struct pci_dev isa_dev[MAX_CARDS];
518static int io[MAX_CARDS];
519static int irq[MAX_CARDS];
520static int cardnr[MAX_CARDS];
521
522MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i");
523MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i");
524MODULE_PARM(cardnr, "1-" __MODULE_STRING(MAX_CARDS) "i");
525MODULE_PARM_DESC(io, "I/O base address(es)");
526MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
527MODULE_PARM_DESC(cardnr, "Card number(s) (as jumpered)");
528
529static int t1isa_add_card(struct capi_driver *driver, capicardparams *data)
530{
531 int i;
532
533 for (i = 0; i < MAX_CARDS; i++) {
534 if (isa_dev[i].resource[0].start)
535 continue;
536
537 isa_dev[i].resource[0].start = data->port;
538 isa_dev[i].irq = data->irq;
539
540 if (t1isa_probe(&isa_dev[i], data->cardnr) == 0)
541 return 0;
542 }
543 return -ENODEV;
544}
545
546static struct capi_driver capi_driver_t1isa = {
547 .name = "t1isa",
548 .revision = "1.0",
549 .add_card = t1isa_add_card,
550};
551
552static int __init t1isa_init(void)
553{
554 char rev[32];
555 char *p;
556 int i;
557
558 if ((p = strchr(revision, ':')) != 0 && p[1]) {
559 strlcpy(rev, p + 2, 32);
560 if ((p = strchr(rev, '$')) != 0 && p > rev)
561 *(p-1) = 0;
562 } else
563 strcpy(rev, "1.0");
564
565 for (i = 0; i < MAX_CARDS; i++) {
566 if (!io[i])
567 break;
568
569 isa_dev[i].resource[0].start = io[i];
570 isa_dev[i].irq = irq[i];
571
572 if (t1isa_probe(&isa_dev[i], cardnr[i]) != 0)
573 return -ENODEV;
574 }
575
576 strlcpy(capi_driver_t1isa.revision, rev, 32);
577 register_capi_driver(&capi_driver_t1isa);
578 printk(KERN_INFO "t1isa: revision %s\n", rev);
579
580 return 0;
581}
582
583static void __exit t1isa_exit(void)
584{
585 int i;
586
587 for (i = 0; i < MAX_CARDS; i++) {
588 if (!io[i])
589 break;
590
591 t1isa_remove(&isa_dev[i]);
592 }
593}
594
595module_init(t1isa_init);
596module_exit(t1isa_exit);
diff --git a/drivers/isdn/hardware/avm/t1pci.c b/drivers/isdn/hardware/avm/t1pci.c
new file mode 100644
index 000000000000..2ceec8e8419f
--- /dev/null
+++ b/drivers/isdn/hardware/avm/t1pci.c
@@ -0,0 +1,260 @@
1/* $Id: t1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
2 *
3 * Module for AVM T1 PCI-card.
4 *
5 * Copyright 1999 by Carsten Paeth <calle@calle.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/config.h>
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/skbuff.h>
16#include <linux/delay.h>
17#include <linux/mm.h>
18#include <linux/interrupt.h>
19#include <linux/ioport.h>
20#include <linux/pci.h>
21#include <linux/capi.h>
22#include <linux/init.h>
23#include <asm/io.h>
24#include <linux/isdn/capicmd.h>
25#include <linux/isdn/capiutil.h>
26#include <linux/isdn/capilli.h>
27#include "avmcard.h"
28
29#undef CONFIG_T1PCI_DEBUG
30#undef CONFIG_T1PCI_POLLDEBUG
31
32/* ------------------------------------------------------------- */
33static char *revision = "$Revision: 1.1.2.2 $";
34/* ------------------------------------------------------------- */
35
36static struct pci_device_id t1pci_pci_tbl[] = {
37 { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, PCI_ANY_ID, PCI_ANY_ID },
38 { } /* Terminating entry */
39};
40
41MODULE_DEVICE_TABLE(pci, t1pci_pci_tbl);
42MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 PCI card");
43MODULE_AUTHOR("Carsten Paeth");
44MODULE_LICENSE("GPL");
45
46/* ------------------------------------------------------------- */
47
48static char *t1pci_procinfo(struct capi_ctr *ctrl);
49
50static int t1pci_add_card(struct capicardparams *p, struct pci_dev *pdev)
51{
52 avmcard *card;
53 avmctrl_info *cinfo;
54 int retval;
55
56 card = b1_alloc_card(1);
57 if (!card) {
58 printk(KERN_WARNING "t1pci: no memory.\n");
59 retval = -ENOMEM;
60 goto err;
61 }
62
63 card->dma = avmcard_dma_alloc("t1pci", pdev, 2048+128, 2048+128);
64 if (!card->dma) {
65 printk(KERN_WARNING "t1pci: no memory.\n");
66 retval = -ENOMEM;
67 goto err_free;
68 }
69
70 cinfo = card->ctrlinfo;
71 sprintf(card->name, "t1pci-%x", p->port);
72 card->port = p->port;
73 card->irq = p->irq;
74 card->membase = p->membase;
75 card->cardtype = avm_t1pci;
76
77 if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
78 printk(KERN_WARNING "t1pci: ports 0x%03x-0x%03x in use.\n",
79 card->port, card->port + AVMB1_PORTLEN);
80 retval = -EBUSY;
81 goto err_free_dma;
82 }
83
84 card->mbase = ioremap(card->membase, 64);
85 if (!card->mbase) {
86 printk(KERN_NOTICE "t1pci: can't remap memory at 0x%lx\n",
87 card->membase);
88 retval = -EIO;
89 goto err_release_region;
90 }
91
92 b1dma_reset(card);
93
94 retval = t1pci_detect(card);
95 if (retval != 0) {
96 if (retval < 6)
97 printk(KERN_NOTICE "t1pci: NO card at 0x%x (%d)\n",
98 card->port, retval);
99 else
100 printk(KERN_NOTICE "t1pci: card at 0x%x, but cable not connected or T1 has no power (%d)\n",
101 card->port, retval);
102 retval = -EIO;
103 goto err_unmap;
104 }
105 b1dma_reset(card);
106
107 retval = request_irq(card->irq, b1dma_interrupt, SA_SHIRQ, card->name, card);
108 if (retval) {
109 printk(KERN_ERR "t1pci: unable to get IRQ %d.\n", card->irq);
110 retval = -EBUSY;
111 goto err_unmap;
112 }
113
114 cinfo->capi_ctrl.owner = THIS_MODULE;
115 cinfo->capi_ctrl.driver_name = "t1pci";
116 cinfo->capi_ctrl.driverdata = cinfo;
117 cinfo->capi_ctrl.register_appl = b1dma_register_appl;
118 cinfo->capi_ctrl.release_appl = b1dma_release_appl;
119 cinfo->capi_ctrl.send_message = b1dma_send_message;
120 cinfo->capi_ctrl.load_firmware = b1dma_load_firmware;
121 cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr;
122 cinfo->capi_ctrl.procinfo = t1pci_procinfo;
123 cinfo->capi_ctrl.ctr_read_proc = b1dmactl_read_proc;
124 strcpy(cinfo->capi_ctrl.name, card->name);
125
126 retval = attach_capi_ctr(&cinfo->capi_ctrl);
127 if (retval) {
128 printk(KERN_ERR "t1pci: attach controller failed.\n");
129 retval = -EBUSY;
130 goto err_free_irq;
131 }
132 card->cardnr = cinfo->capi_ctrl.cnr;
133
134 printk(KERN_INFO "t1pci: AVM T1 PCI at i/o %#x, irq %d, mem %#lx\n",
135 card->port, card->irq, card->membase);
136
137 pci_set_drvdata(pdev, card);
138 return 0;
139
140 err_free_irq:
141 free_irq(card->irq, card);
142 err_unmap:
143 iounmap(card->mbase);
144 err_release_region:
145 release_region(card->port, AVMB1_PORTLEN);
146 err_free_dma:
147 avmcard_dma_free(card->dma);
148 err_free:
149 b1_free_card(card);
150 err:
151 return retval;
152}
153
154/* ------------------------------------------------------------- */
155
156static void t1pci_remove(struct pci_dev *pdev)
157{
158 avmcard *card = pci_get_drvdata(pdev);
159 avmctrl_info *cinfo = card->ctrlinfo;
160
161 b1dma_reset(card);
162
163 detach_capi_ctr(&cinfo->capi_ctrl);
164 free_irq(card->irq, card);
165 iounmap(card->mbase);
166 release_region(card->port, AVMB1_PORTLEN);
167 avmcard_dma_free(card->dma);
168 b1_free_card(card);
169}
170
171/* ------------------------------------------------------------- */
172
173static char *t1pci_procinfo(struct capi_ctr *ctrl)
174{
175 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
176
177 if (!cinfo)
178 return "";
179 sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx",
180 cinfo->cardname[0] ? cinfo->cardname : "-",
181 cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
182 cinfo->card ? cinfo->card->port : 0x0,
183 cinfo->card ? cinfo->card->irq : 0,
184 cinfo->card ? cinfo->card->membase : 0
185 );
186 return cinfo->infobuf;
187}
188
189/* ------------------------------------------------------------- */
190
191static int __devinit t1pci_probe(struct pci_dev *dev,
192 const struct pci_device_id *ent)
193{
194 struct capicardparams param;
195 int retval;
196
197 if (pci_enable_device(dev) < 0) {
198 printk(KERN_ERR "t1pci: failed to enable AVM-T1-PCI\n");
199 return -ENODEV;
200 }
201 pci_set_master(dev);
202
203 param.port = pci_resource_start(dev, 1);
204 param.irq = dev->irq;
205 param.membase = pci_resource_start(dev, 0);
206
207 printk(KERN_INFO "t1pci: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n",
208 param.port, param.irq, param.membase);
209
210 retval = t1pci_add_card(&param, dev);
211 if (retval != 0) {
212 printk(KERN_ERR "t1pci: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n",
213 param.port, param.irq, param.membase);
214 return -ENODEV;
215 }
216 return 0;
217}
218
219static struct pci_driver t1pci_pci_driver = {
220 .name = "t1pci",
221 .id_table = t1pci_pci_tbl,
222 .probe = t1pci_probe,
223 .remove = t1pci_remove,
224};
225
226static struct capi_driver capi_driver_t1pci = {
227 .name = "t1pci",
228 .revision = "1.0",
229};
230
231static int __init t1pci_init(void)
232{
233 char *p;
234 char rev[32];
235 int err;
236
237 if ((p = strchr(revision, ':')) != 0 && p[1]) {
238 strlcpy(rev, p + 2, 32);
239 if ((p = strchr(rev, '$')) != 0 && p > rev)
240 *(p-1) = 0;
241 } else
242 strcpy(rev, "1.0");
243
244 err = pci_register_driver(&t1pci_pci_driver);
245 if (!err) {
246 strlcpy(capi_driver_t1pci.revision, rev, 32);
247 register_capi_driver(&capi_driver_t1pci);
248 printk(KERN_INFO "t1pci: revision %s\n", rev);
249 }
250 return err;
251}
252
253static void __exit t1pci_exit(void)
254{
255 unregister_capi_driver(&capi_driver_t1pci);
256 pci_unregister_driver(&t1pci_pci_driver);
257}
258
259module_init(t1pci_init);
260module_exit(t1pci_exit);
diff --git a/drivers/isdn/hardware/eicon/Kconfig b/drivers/isdn/hardware/eicon/Kconfig
new file mode 100644
index 000000000000..51e66bc64208
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/Kconfig
@@ -0,0 +1,53 @@
1#
2# ISDN DIVAS Eicon driver
3#
4
5menu "Active Eicon DIVA Server cards"
6 depends on NET && ISDN && ISDN_CAPI!=n
7
8config CAPI_EICON
9 bool "Support Eicon cards"
10 help
11 Enable support for Eicon Networks active ISDN cards.
12
13config ISDN_DIVAS
14 tristate "Support Eicon DIVA Server cards"
15 depends on CAPI_EICON && PROC_FS && PCI
16 help
17 Say Y here if you have an Eicon Networks DIVA Server PCI ISDN card.
18 In order to use this card, additional firmware is necessary, which
19 has to be downloaded into the card using the divactrl utility.
20
21config ISDN_DIVAS_BRIPCI
22 bool "DIVA Server BRI/PCI support"
23 depends on ISDN_DIVAS
24 help
25 Enable support for DIVA Server BRI-PCI.
26
27config ISDN_DIVAS_PRIPCI
28 bool "DIVA Server PRI/PCI support"
29 depends on ISDN_DIVAS
30 help
31 Enable support for DIVA Server PRI-PCI.
32
33config ISDN_DIVAS_DIVACAPI
34 tristate "DIVA CAPI2.0 interface support"
35 depends on ISDN_DIVAS && ISDN_CAPI
36 help
37 You need this to provide the CAPI interface
38 for DIVA Server cards.
39
40config ISDN_DIVAS_USERIDI
41 tristate "DIVA User-IDI interface support"
42 depends on ISDN_DIVAS
43 help
44 Enable support for user-mode IDI interface.
45
46config ISDN_DIVAS_MAINT
47 tristate "DIVA Maint driver support"
48 depends on ISDN_DIVAS && m
49 help
50 Enable Divas Maintainance driver.
51
52endmenu
53
diff --git a/drivers/isdn/hardware/eicon/Makefile b/drivers/isdn/hardware/eicon/Makefile
new file mode 100644
index 000000000000..4fa7fdb7df0d
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/Makefile
@@ -0,0 +1,23 @@
1# Makefile for the Eicon DIVA ISDN drivers.
2
3# Each configuration option enables a list of files.
4
5obj-$(CONFIG_ISDN_DIVAS) += divadidd.o divas.o
6obj-$(CONFIG_ISDN_DIVAS_MAINT) += diva_mnt.o
7obj-$(CONFIG_ISDN_DIVAS_USERIDI) += diva_idi.o
8obj-$(CONFIG_ISDN_DIVAS_DIVACAPI) += divacapi.o
9
10# Multipart objects.
11
12divas-y := divasmain.o divasfunc.o di.o io.o istream.o \
13 diva.o divasproc.o diva_dma.o
14divas-$(CONFIG_ISDN_DIVAS_BRIPCI) += os_bri.o s_bri.o os_4bri.o s_4bri.o
15divas-$(CONFIG_ISDN_DIVAS_PRIPCI) += os_pri.o s_pri.o
16
17divacapi-y := capimain.o capifunc.o message.o capidtmf.o
18
19divadidd-y := diva_didd.o diddfunc.o dadapter.o
20
21diva_mnt-y := divamnt.o mntfunc.o debug.o maintidi.o
22
23diva_idi-y := divasi.o idifunc.o um_idi.o dqueue.o
diff --git a/drivers/isdn/hardware/eicon/adapter.h b/drivers/isdn/hardware/eicon/adapter.h
new file mode 100644
index 000000000000..71a7c2f084a7
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/adapter.h
@@ -0,0 +1,17 @@
1/* $Id: adapter.h,v 1.4 2004/03/21 17:26:01 armin Exp $ */
2
3#ifndef __DIVA_USER_MODE_IDI_ADAPTER_H__
4#define __DIVA_USER_MODE_IDI_ADAPTER_H__
5
6#define DIVA_UM_IDI_ADAPTER_REMOVED 0x00000001
7
8typedef struct _diva_um_idi_adapter {
9 struct list_head link;
10 DESCRIPTOR d;
11 int adapter_nr;
12 struct list_head entity_q; /* entities linked to this adapter */
13 dword status;
14} diva_um_idi_adapter_t;
15
16
17#endif
diff --git a/drivers/isdn/hardware/eicon/capi20.h b/drivers/isdn/hardware/eicon/capi20.h
new file mode 100644
index 000000000000..7ebcccda74d8
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/capi20.h
@@ -0,0 +1,699 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef _INC_CAPI20
27#define _INC_CAPI20
28 /* operations on message queues */
29 /* the common device type for CAPI20 drivers */
30#define FILE_DEVICE_CAPI20 0x8001
31 /* DEVICE_CONTROL codes for user and kernel mode applications */
32#define CAPI20_CTL_REGISTER 0x0801
33#define CAPI20_CTL_RELEASE 0x0802
34#define CAPI20_CTL_GET_MANUFACTURER 0x0805
35#define CAPI20_CTL_GET_VERSION 0x0806
36#define CAPI20_CTL_GET_SERIAL 0x0807
37#define CAPI20_CTL_GET_PROFILE 0x0808
38 /* INTERNAL_DEVICE_CONTROL codes for kernel mode applicatios only */
39#define CAPI20_CTL_PUT_MESSAGE 0x0803
40#define CAPI20_CTL_GET_MESSAGE 0x0804
41 /* the wrapped codes as required by the system */
42#define CAPI_CTL_CODE(f,m) CTL_CODE(FILE_DEVICE_CAPI20,f,m,FILE_ANY_ACCESS)
43#define IOCTL_CAPI_REGISTER CAPI_CTL_CODE(CAPI20_CTL_REGISTER,METHOD_BUFFERED)
44#define IOCTL_CAPI_RELEASE CAPI_CTL_CODE(CAPI20_CTL_RELEASE,METHOD_BUFFERED)
45#define IOCTL_CAPI_GET_MANUFACTURER CAPI_CTL_CODE(CAPI20_CTL_GET_MANUFACTURER,METHOD_BUFFERED)
46#define IOCTL_CAPI_GET_VERSION CAPI_CTL_CODE(CAPI20_CTL_GET_VERSION,METHOD_BUFFERED)
47#define IOCTL_CAPI_GET_SERIAL CAPI_CTL_CODE(CAPI20_CTL_GET_SERIAL,METHOD_BUFFERED)
48#define IOCTL_CAPI_GET_PROFILE CAPI_CTL_CODE(CAPI20_CTL_GET_PROFILE,METHOD_BUFFERED)
49#define IOCTL_CAPI_PUT_MESSAGE CAPI_CTL_CODE(CAPI20_CTL_PUT_MESSAGE,METHOD_BUFFERED)
50#define IOCTL_CAPI_GET_MESSAGE CAPI_CTL_CODE(CAPI20_CTL_GET_MESSAGE,METHOD_BUFFERED)
51struct divas_capi_register_params {
52 word MessageBufferSize;
53 word maxLogicalConnection;
54 word maxBDataBlocks;
55 word maxBDataLen;
56};
57struct divas_capi_version {
58 word CapiMajor;
59 word CapiMinor;
60 word ManuMajor;
61 word ManuMinor;
62};
63typedef struct api_profile_s {
64 word Number;
65 word Channels;
66 dword Global_Options;
67 dword B1_Protocols;
68 dword B2_Protocols;
69 dword B3_Protocols;
70} API_PROFILE;
71 /* ISDN Common API message types */
72#define _ALERT_R 0x8001
73#define _CONNECT_R 0x8002
74#define _CONNECT_I 0x8202
75#define _CONNECT_ACTIVE_I 0x8203
76#define _DISCONNECT_R 0x8004
77#define _DISCONNECT_I 0x8204
78#define _LISTEN_R 0x8005
79#define _INFO_R 0x8008
80#define _INFO_I 0x8208
81#define _SELECT_B_REQ 0x8041
82#define _FACILITY_R 0x8080
83#define _FACILITY_I 0x8280
84#define _CONNECT_B3_R 0x8082
85#define _CONNECT_B3_I 0x8282
86#define _CONNECT_B3_ACTIVE_I 0x8283
87#define _DISCONNECT_B3_R 0x8084
88#define _DISCONNECT_B3_I 0x8284
89#define _DATA_B3_R 0x8086
90#define _DATA_B3_I 0x8286
91#define _RESET_B3_R 0x8087
92#define _RESET_B3_I 0x8287
93#define _CONNECT_B3_T90_ACTIVE_I 0x8288
94#define _MANUFACTURER_R 0x80ff
95#define _MANUFACTURER_I 0x82ff
96 /* OR this to convert a REQUEST to a CONFIRM */
97#define CONFIRM 0x0100
98 /* OR this to convert a INDICATION to a RESPONSE */
99#define RESPONSE 0x0100
100/*------------------------------------------------------------------*/
101/* diehl isdn private MANUFACTURER codes */
102/*------------------------------------------------------------------*/
103#define _DI_MANU_ID 0x44444944
104#define _DI_ASSIGN_PLCI 0x0001
105#define _DI_ADV_CODEC 0x0002
106#define _DI_DSP_CTRL 0x0003
107#define _DI_SIG_CTRL 0x0004
108#define _DI_RXT_CTRL 0x0005
109#define _DI_IDI_CTRL 0x0006
110#define _DI_CFG_CTRL 0x0007
111#define _DI_REMOVE_CODEC 0x0008
112#define _DI_OPTIONS_REQUEST 0x0009
113#define _DI_SSEXT_CTRL 0x000a
114#define _DI_NEGOTIATE_B3 0x000b
115/*------------------------------------------------------------------*/
116/* parameter structures */
117/*------------------------------------------------------------------*/
118 /* ALERT-REQUEST */
119typedef struct {
120 byte structs[1]; /* Additional Info */
121} _ALT_REQP;
122 /* ALERT-CONFIRM */
123typedef struct {
124 word Info;
125} _ALT_CONP;
126 /* CONNECT-REQUEST */
127typedef struct {
128 word CIP_Value;
129 byte structs[1]; /* Called party number,
130 Called party subaddress,
131 Calling party number,
132 Calling party subaddress,
133 B_protocol,
134 BC,
135 LLC,
136 HLC,
137 Additional Info */
138} _CON_REQP;
139 /* CONNECT-CONFIRM */
140typedef struct {
141 word Info;
142} _CON_CONP;
143 /* CONNECT-INDICATION */
144typedef struct {
145 word CIP_Value;
146 byte structs[1]; /* Called party number,
147 Called party subaddress,
148 Calling party number,
149 Calling party subaddress,
150 BC,
151 LLC,
152 HLC,
153 Additional Info */
154} _CON_INDP;
155 /* CONNECT-RESPONSE */
156typedef struct {
157 word Accept;
158 byte structs[1]; /* B_protocol,
159 Connected party number,
160 Connected party subaddress,
161 LLC */
162} _CON_RESP;
163 /* CONNECT-ACTIVE-INDICATION */
164typedef struct {
165 byte structs[1]; /* Connected party number,
166 Connected party subaddress,
167 LLC */
168} _CON_A_INDP;
169 /* CONNECT-ACTIVE-RESPONSE */
170typedef struct {
171 byte structs[1]; /* empty */
172} _CON_A_RESP;
173 /* DISCONNECT-REQUEST */
174typedef struct {
175 byte structs[1]; /* Additional Info */
176} _DIS_REQP;
177 /* DISCONNECT-CONFIRM */
178typedef struct {
179 word Info;
180} _DIS_CONP;
181 /* DISCONNECT-INDICATION */
182typedef struct {
183 word Info;
184} _DIS_INDP;
185 /* DISCONNECT-RESPONSE */
186typedef struct {
187 byte structs[1]; /* empty */
188} _DIS_RESP;
189 /* LISTEN-REQUEST */
190typedef struct {
191 dword Info_Mask;
192 dword CIP_Mask;
193 byte structs[1]; /* Calling party number,
194 Calling party subaddress */
195} _LIS_REQP;
196 /* LISTEN-CONFIRM */
197typedef struct {
198 word Info;
199} _LIS_CONP;
200 /* INFO-REQUEST */
201typedef struct {
202 byte structs[1]; /* Called party number,
203 Additional Info */
204} _INF_REQP;
205 /* INFO-CONFIRM */
206typedef struct {
207 word Info;
208} _INF_CONP;
209 /* INFO-INDICATION */
210typedef struct {
211 word Number;
212 byte structs[1]; /* Info element */
213} _INF_INDP;
214 /* INFO-RESPONSE */
215typedef struct {
216 byte structs[1]; /* empty */
217} _INF_RESP;
218 /* SELECT-B-REQUEST */
219typedef struct {
220 byte structs[1]; /* B-protocol */
221} _SEL_B_REQP;
222 /* SELECT-B-CONFIRM */
223typedef struct {
224 word Info;
225} _SEL_B_CONP;
226 /* FACILITY-REQUEST */
227typedef struct {
228 word Selector;
229 byte structs[1]; /* Facility parameters */
230} _FAC_REQP;
231 /* FACILITY-CONFIRM STRUCT FOR SUPPLEMENT. SERVICES */
232typedef struct {
233 byte struct_length;
234 word function;
235 byte length;
236 word SupplementaryServiceInfo;
237 dword SupportedServices;
238} _FAC_CON_STRUCTS;
239 /* FACILITY-CONFIRM */
240typedef struct {
241 word Info;
242 word Selector;
243 byte structs[1]; /* Facility parameters */
244} _FAC_CONP;
245 /* FACILITY-INDICATION */
246typedef struct {
247 word Selector;
248 byte structs[1]; /* Facility parameters */
249} _FAC_INDP;
250 /* FACILITY-RESPONSE */
251typedef struct {
252 word Selector;
253 byte structs[1]; /* Facility parameters */
254} _FAC_RESP;
255 /* CONNECT-B3-REQUEST */
256typedef struct {
257 byte structs[1]; /* NCPI */
258} _CON_B3_REQP;
259 /* CONNECT-B3-CONFIRM */
260typedef struct {
261 word Info;
262} _CON_B3_CONP;
263 /* CONNECT-B3-INDICATION */
264typedef struct {
265 byte structs[1]; /* NCPI */
266} _CON_B3_INDP;
267 /* CONNECT-B3-RESPONSE */
268typedef struct {
269 word Accept;
270 byte structs[1]; /* NCPI */
271} _CON_B3_RESP;
272 /* CONNECT-B3-ACTIVE-INDICATION */
273typedef struct {
274 byte structs[1]; /* NCPI */
275} _CON_B3_A_INDP;
276 /* CONNECT-B3-ACTIVE-RESPONSE */
277typedef struct {
278 byte structs[1]; /* empty */
279} _CON_B3_A_RESP;
280 /* DISCONNECT-B3-REQUEST */
281typedef struct {
282 byte structs[1]; /* NCPI */
283} _DIS_B3_REQP;
284 /* DISCONNECT-B3-CONFIRM */
285typedef struct {
286 word Info;
287} _DIS_B3_CONP;
288 /* DISCONNECT-B3-INDICATION */
289typedef struct {
290 word Info;
291 byte structs[1]; /* NCPI */
292} _DIS_B3_INDP;
293 /* DISCONNECT-B3-RESPONSE */
294typedef struct {
295 byte structs[1]; /* empty */
296} _DIS_B3_RESP;
297 /* DATA-B3-REQUEST */
298typedef struct {
299 dword Data;
300 word Data_Length;
301 word Number;
302 word Flags;
303} _DAT_B3_REQP;
304 /* DATA-B3-REQUEST 64 BIT Systems */
305typedef struct {
306 dword Data;
307 word Data_Length;
308 word Number;
309 word Flags;
310 void *pData;
311} _DAT_B3_REQ64P;
312 /* DATA-B3-CONFIRM */
313typedef struct {
314 word Number;
315 word Info;
316} _DAT_B3_CONP;
317 /* DATA-B3-INDICATION */
318typedef struct {
319 dword Data;
320 word Data_Length;
321 word Number;
322 word Flags;
323} _DAT_B3_INDP;
324 /* DATA-B3-INDICATION 64 BIT Systems */
325typedef struct {
326 dword Data;
327 word Data_Length;
328 word Number;
329 word Flags;
330 void *pData;
331} _DAT_B3_IND64P;
332 /* DATA-B3-RESPONSE */
333typedef struct {
334 word Number;
335} _DAT_B3_RESP;
336 /* RESET-B3-REQUEST */
337typedef struct {
338 byte structs[1]; /* NCPI */
339} _RES_B3_REQP;
340 /* RESET-B3-CONFIRM */
341typedef struct {
342 word Info;
343} _RES_B3_CONP;
344 /* RESET-B3-INDICATION */
345typedef struct {
346 byte structs[1]; /* NCPI */
347} _RES_B3_INDP;
348 /* RESET-B3-RESPONSE */
349typedef struct {
350 byte structs[1]; /* empty */
351} _RES_B3_RESP;
352 /* CONNECT-B3-T90-ACTIVE-INDICATION */
353typedef struct {
354 byte structs[1]; /* NCPI */
355} _CON_B3_T90_A_INDP;
356 /* CONNECT-B3-T90-ACTIVE-RESPONSE */
357typedef struct {
358 word Reject;
359 byte structs[1]; /* NCPI */
360} _CON_B3_T90_A_RESP;
361/*------------------------------------------------------------------*/
362/* message structure */
363/*------------------------------------------------------------------*/
364typedef struct _API_MSG CAPI_MSG;
365typedef struct _MSG_HEADER CAPI_MSG_HEADER;
366struct _API_MSG {
367 struct _MSG_HEADER {
368 word length;
369 word appl_id;
370 word command;
371 word number;
372 byte controller;
373 byte plci;
374 word ncci;
375 } header;
376 union {
377 _ALT_REQP alert_req;
378 _ALT_CONP alert_con;
379 _CON_REQP connect_req;
380 _CON_CONP connect_con;
381 _CON_INDP connect_ind;
382 _CON_RESP connect_res;
383 _CON_A_INDP connect_a_ind;
384 _CON_A_RESP connect_a_res;
385 _DIS_REQP disconnect_req;
386 _DIS_CONP disconnect_con;
387 _DIS_INDP disconnect_ind;
388 _DIS_RESP disconnect_res;
389 _LIS_REQP listen_req;
390 _LIS_CONP listen_con;
391 _INF_REQP info_req;
392 _INF_CONP info_con;
393 _INF_INDP info_ind;
394 _INF_RESP info_res;
395 _SEL_B_REQP select_b_req;
396 _SEL_B_CONP select_b_con;
397 _FAC_REQP facility_req;
398 _FAC_CONP facility_con;
399 _FAC_INDP facility_ind;
400 _FAC_RESP facility_res;
401 _CON_B3_REQP connect_b3_req;
402 _CON_B3_CONP connect_b3_con;
403 _CON_B3_INDP connect_b3_ind;
404 _CON_B3_RESP connect_b3_res;
405 _CON_B3_A_INDP connect_b3_a_ind;
406 _CON_B3_A_RESP connect_b3_a_res;
407 _DIS_B3_REQP disconnect_b3_req;
408 _DIS_B3_CONP disconnect_b3_con;
409 _DIS_B3_INDP disconnect_b3_ind;
410 _DIS_B3_RESP disconnect_b3_res;
411 _DAT_B3_REQP data_b3_req;
412 _DAT_B3_REQ64P data_b3_req64;
413 _DAT_B3_CONP data_b3_con;
414 _DAT_B3_INDP data_b3_ind;
415 _DAT_B3_IND64P data_b3_ind64;
416 _DAT_B3_RESP data_b3_res;
417 _RES_B3_REQP reset_b3_req;
418 _RES_B3_CONP reset_b3_con;
419 _RES_B3_INDP reset_b3_ind;
420 _RES_B3_RESP reset_b3_res;
421 _CON_B3_T90_A_INDP connect_b3_t90_a_ind;
422 _CON_B3_T90_A_RESP connect_b3_t90_a_res;
423 byte b[200];
424 } info;
425};
426/*------------------------------------------------------------------*/
427/* non-fatal errors */
428/*------------------------------------------------------------------*/
429#define _NCPI_IGNORED 0x0001
430#define _FLAGS_IGNORED 0x0002
431#define _ALERT_IGNORED 0x0003
432/*------------------------------------------------------------------*/
433/* API function error codes */
434/*------------------------------------------------------------------*/
435#define GOOD 0x0000
436#define _TOO_MANY_APPLICATIONS 0x1001
437#define _BLOCK_TOO_SMALL 0x1002
438#define _BUFFER_TOO_BIG 0x1003
439#define _MSG_BUFFER_TOO_SMALL 0x1004
440#define _TOO_MANY_CONNECTIONS 0x1005
441#define _REG_CAPI_BUSY 0x1007
442#define _REG_RESOURCE_ERROR 0x1008
443#define _REG_CAPI_NOT_INSTALLED 0x1009
444#define _WRONG_APPL_ID 0x1101
445#define _BAD_MSG 0x1102
446#define _QUEUE_FULL 0x1103
447#define _GET_NO_MSG 0x1104
448#define _MSG_LOST 0x1105
449#define _WRONG_NOTIFY 0x1106
450#define _CAPI_BUSY 0x1107
451#define _RESOURCE_ERROR 0x1108
452#define _CAPI_NOT_INSTALLED 0x1109
453#define _NO_EXTERNAL_EQUIPMENT 0x110a
454#define _ONLY_EXTERNAL_EQUIPMENT 0x110b
455/*------------------------------------------------------------------*/
456/* addressing/coding error codes */
457/*------------------------------------------------------------------*/
458#define _WRONG_STATE 0x2001
459#define _WRONG_IDENTIFIER 0x2002
460#define _OUT_OF_PLCI 0x2003
461#define _OUT_OF_NCCI 0x2004
462#define _OUT_OF_LISTEN 0x2005
463#define _OUT_OF_FAX 0x2006
464#define _WRONG_MESSAGE_FORMAT 0x2007
465#define _OUT_OF_INTERCONNECT_RESOURCES 0x2008
466/*------------------------------------------------------------------*/
467/* configuration error codes */
468/*------------------------------------------------------------------*/
469#define _B1_NOT_SUPPORTED 0x3001
470#define _B2_NOT_SUPPORTED 0x3002
471#define _B3_NOT_SUPPORTED 0x3003
472#define _B1_PARM_NOT_SUPPORTED 0x3004
473#define _B2_PARM_NOT_SUPPORTED 0x3005
474#define _B3_PARM_NOT_SUPPORTED 0x3006
475#define _B_STACK_NOT_SUPPORTED 0x3007
476#define _NCPI_NOT_SUPPORTED 0x3008
477#define _CIP_NOT_SUPPORTED 0x3009
478#define _FLAGS_NOT_SUPPORTED 0x300a
479#define _FACILITY_NOT_SUPPORTED 0x300b
480#define _DATA_LEN_NOT_SUPPORTED 0x300c
481#define _RESET_NOT_SUPPORTED 0x300d
482#define _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED 0x300e
483#define _REQUEST_NOT_ALLOWED_IN_THIS_STATE 0x3010
484#define _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP 0x3011
485/*------------------------------------------------------------------*/
486/* reason codes */
487/*------------------------------------------------------------------*/
488#define _L1_ERROR 0x3301
489#define _L2_ERROR 0x3302
490#define _L3_ERROR 0x3303
491#define _OTHER_APPL_CONNECTED 0x3304
492#define _CAPI_GUARD_ERROR 0x3305
493#define _L3_CAUSE 0x3400
494/*------------------------------------------------------------------*/
495/* b3 reason codes */
496/*------------------------------------------------------------------*/
497#define _B_CHANNEL_LOST 0x3301
498#define _B2_ERROR 0x3302
499#define _B3_ERROR 0x3303
500/*------------------------------------------------------------------*/
501/* fax error codes */
502/*------------------------------------------------------------------*/
503#define _FAX_NO_CONNECTION 0x3311
504#define _FAX_TRAINING_ERROR 0x3312
505#define _FAX_REMOTE_REJECT 0x3313
506#define _FAX_REMOTE_ABORT 0x3314
507#define _FAX_PROTOCOL_ERROR 0x3315
508#define _FAX_TX_UNDERRUN 0x3316
509#define _FAX_RX_OVERFLOW 0x3317
510#define _FAX_LOCAL_ABORT 0x3318
511#define _FAX_PARAMETER_ERROR 0x3319
512/*------------------------------------------------------------------*/
513/* line interconnect error codes */
514/*------------------------------------------------------------------*/
515#define _LI_USER_INITIATED 0x0000
516#define _LI_LINE_NO_LONGER_AVAILABLE 0x3805
517#define _LI_INTERCONNECT_NOT_ESTABLISHED 0x3806
518#define _LI_LINES_NOT_COMPATIBLE 0x3807
519#define _LI2_USER_INITIATED 0x0000
520#define _LI2_PLCI_HAS_NO_BCHANNEL 0x3800
521#define _LI2_LINES_NOT_COMPATIBLE 0x3801
522#define _LI2_NOT_IN_SAME_INTERCONNECTION 0x3802
523/*------------------------------------------------------------------*/
524/* global options */
525/*------------------------------------------------------------------*/
526#define GL_INTERNAL_CONTROLLER_SUPPORTED 0x00000001L
527#define GL_EXTERNAL_EQUIPMENT_SUPPORTED 0x00000002L
528#define GL_HANDSET_SUPPORTED 0x00000004L
529#define GL_DTMF_SUPPORTED 0x00000008L
530#define GL_SUPPLEMENTARY_SERVICES_SUPPORTED 0x00000010L
531#define GL_CHANNEL_ALLOCATION_SUPPORTED 0x00000020L
532#define GL_BCHANNEL_OPERATION_SUPPORTED 0x00000040L
533#define GL_LINE_INTERCONNECT_SUPPORTED 0x00000080L
534#define GL_ECHO_CANCELLER_SUPPORTED 0x00000100L
535/*------------------------------------------------------------------*/
536/* protocol selection */
537/*------------------------------------------------------------------*/
538#define B1_HDLC 0
539#define B1_TRANSPARENT 1
540#define B1_V110_ASYNC 2
541#define B1_V110_SYNC 3
542#define B1_T30 4
543#define B1_HDLC_INVERTED 5
544#define B1_TRANSPARENT_R 6
545#define B1_MODEM_ALL_NEGOTIATE 7
546#define B1_MODEM_ASYNC 8
547#define B1_MODEM_SYNC_HDLC 9
548#define B2_X75 0
549#define B2_TRANSPARENT 1
550#define B2_SDLC 2
551#define B2_LAPD 3
552#define B2_T30 4
553#define B2_PPP 5
554#define B2_TRANSPARENT_NO_CRC 6
555#define B2_MODEM_EC_COMPRESSION 7
556#define B2_X75_V42BIS 8
557#define B2_V120_ASYNC 9
558#define B2_V120_ASYNC_V42BIS 10
559#define B2_V120_BIT_TRANSPARENT 11
560#define B2_LAPD_FREE_SAPI_SEL 12
561#define B3_TRANSPARENT 0
562#define B3_T90NL 1
563#define B3_ISO8208 2
564#define B3_X25_DCE 3
565#define B3_T30 4
566#define B3_T30_WITH_EXTENSIONS 5
567#define B3_RESERVED 6
568#define B3_MODEM 7
569/*------------------------------------------------------------------*/
570/* facility definitions */
571/*------------------------------------------------------------------*/
572#define SELECTOR_HANDSET 0
573#define SELECTOR_DTMF 1
574#define SELECTOR_V42BIS 2
575#define SELECTOR_SU_SERV 3
576#define SELECTOR_POWER_MANAGEMENT 4
577#define SELECTOR_LINE_INTERCONNECT 5
578#define SELECTOR_ECHO_CANCELLER 6
579/*------------------------------------------------------------------*/
580/* supplementary services definitions */
581/*------------------------------------------------------------------*/
582#define S_GET_SUPPORTED_SERVICES 0x0000
583#define S_LISTEN 0x0001
584#define S_HOLD 0x0002
585#define S_RETRIEVE 0x0003
586#define S_SUSPEND 0x0004
587#define S_RESUME 0x0005
588#define S_ECT 0x0006
589#define S_3PTY_BEGIN 0x0007
590#define S_3PTY_END 0x0008
591#define S_CALL_DEFLECTION 0x000d
592#define S_CALL_FORWARDING_START 0x0009
593#define S_CALL_FORWARDING_STOP 0x000a
594#define S_INTERROGATE_DIVERSION 0x000b /* or interrogate parameters */
595#define S_INTERROGATE_NUMBERS 0x000c
596#define S_CCBS_REQUEST 0x000f
597#define S_CCBS_DEACTIVATE 0x0010
598#define S_CCBS_INTERROGATE 0x0011
599#define S_CCBS_CALL 0x0012
600#define S_MWI_ACTIVATE 0x0013
601#define S_MWI_DEACTIVATE 0x0014
602#define S_CONF_BEGIN 0x0017
603#define S_CONF_ADD 0x0018
604#define S_CONF_SPLIT 0x0019
605#define S_CONF_DROP 0x001a
606#define S_CONF_ISOLATE 0x001b
607#define S_CONF_REATTACH 0x001c
608#define S_CCBS_ERASECALLLINKAGEID 0x800d
609#define S_CCBS_STOP_ALERTING 0x8012
610#define S_CCBS_INFO_RETAIN 0x8013
611#define S_MWI_INDICATE 0x8014
612#define S_CONF_PARTYDISC 0x8016
613#define S_CONF_NOTIFICATION 0x8017
614/* Service Masks */
615#define MASK_HOLD_RETRIEVE 0x00000001
616#define MASK_TERMINAL_PORTABILITY 0x00000002
617#define MASK_ECT 0x00000004
618#define MASK_3PTY 0x00000008
619#define MASK_CALL_FORWARDING 0x00000010
620#define MASK_CALL_DEFLECTION 0x00000020
621#define MASK_MWI 0x00000100
622#define MASK_CCNR 0x00000200
623#define MASK_CONF 0x00000400
624/*------------------------------------------------------------------*/
625/* dtmf definitions */
626/*------------------------------------------------------------------*/
627#define DTMF_LISTEN_START 1
628#define DTMF_LISTEN_STOP 2
629#define DTMF_DIGITS_SEND 3
630#define DTMF_SUCCESS 0
631#define DTMF_INCORRECT_DIGIT 1
632#define DTMF_UNKNOWN_REQUEST 2
633/*------------------------------------------------------------------*/
634/* line interconnect definitions */
635/*------------------------------------------------------------------*/
636#define LI_GET_SUPPORTED_SERVICES 0
637#define LI_REQ_CONNECT 1
638#define LI_REQ_DISCONNECT 2
639#define LI_IND_CONNECT_ACTIVE 1
640#define LI_IND_DISCONNECT 2
641#define LI_FLAG_CONFERENCE_A_B ((dword) 0x00000001L)
642#define LI_FLAG_CONFERENCE_B_A ((dword) 0x00000002L)
643#define LI_FLAG_MONITOR_A ((dword) 0x00000004L)
644#define LI_FLAG_MONITOR_B ((dword) 0x00000008L)
645#define LI_FLAG_ANNOUNCEMENT_A ((dword) 0x00000010L)
646#define LI_FLAG_ANNOUNCEMENT_B ((dword) 0x00000020L)
647#define LI_FLAG_MIX_A ((dword) 0x00000040L)
648#define LI_FLAG_MIX_B ((dword) 0x00000080L)
649#define LI_CONFERENCING_SUPPORTED ((dword) 0x00000001L)
650#define LI_MONITORING_SUPPORTED ((dword) 0x00000002L)
651#define LI_ANNOUNCEMENTS_SUPPORTED ((dword) 0x00000004L)
652#define LI_MIXING_SUPPORTED ((dword) 0x00000008L)
653#define LI_CROSS_CONTROLLER_SUPPORTED ((dword) 0x00000010L)
654#define LI2_GET_SUPPORTED_SERVICES 0
655#define LI2_REQ_CONNECT 1
656#define LI2_REQ_DISCONNECT 2
657#define LI2_IND_CONNECT_ACTIVE 1
658#define LI2_IND_DISCONNECT 2
659#define LI2_FLAG_INTERCONNECT_A_B ((dword) 0x00000001L)
660#define LI2_FLAG_INTERCONNECT_B_A ((dword) 0x00000002L)
661#define LI2_FLAG_MONITOR_B ((dword) 0x00000004L)
662#define LI2_FLAG_MIX_B ((dword) 0x00000008L)
663#define LI2_FLAG_MONITOR_X ((dword) 0x00000010L)
664#define LI2_FLAG_MIX_X ((dword) 0x00000020L)
665#define LI2_FLAG_LOOP_B ((dword) 0x00000040L)
666#define LI2_FLAG_LOOP_PC ((dword) 0x00000080L)
667#define LI2_FLAG_LOOP_X ((dword) 0x00000100L)
668#define LI2_CROSS_CONTROLLER_SUPPORTED ((dword) 0x00000001L)
669#define LI2_ASYMMETRIC_SUPPORTED ((dword) 0x00000002L)
670#define LI2_MONITORING_SUPPORTED ((dword) 0x00000004L)
671#define LI2_MIXING_SUPPORTED ((dword) 0x00000008L)
672#define LI2_REMOTE_MONITORING_SUPPORTED ((dword) 0x00000010L)
673#define LI2_REMOTE_MIXING_SUPPORTED ((dword) 0x00000020L)
674#define LI2_B_LOOPING_SUPPORTED ((dword) 0x00000040L)
675#define LI2_PC_LOOPING_SUPPORTED ((dword) 0x00000080L)
676#define LI2_X_LOOPING_SUPPORTED ((dword) 0x00000100L)
677/*------------------------------------------------------------------*/
678/* echo canceller definitions */
679/*------------------------------------------------------------------*/
680#define EC_GET_SUPPORTED_SERVICES 0
681#define EC_ENABLE_OPERATION 1
682#define EC_DISABLE_OPERATION 2
683#define EC_ENABLE_NON_LINEAR_PROCESSING 0x0001
684#define EC_DO_NOT_REQUIRE_REVERSALS 0x0002
685#define EC_DETECT_DISABLE_TONE 0x0004
686#define EC_ENABLE_ADAPTIVE_PREDELAY 0x0008
687#define EC_NON_LINEAR_PROCESSING_SUPPORTED 0x0001
688#define EC_BYPASS_ON_ANY_2100HZ_SUPPORTED 0x0002
689#define EC_BYPASS_ON_REV_2100HZ_SUPPORTED 0x0004
690#define EC_ADAPTIVE_PREDELAY_SUPPORTED 0x0008
691#define EC_BYPASS_INDICATION 1
692#define EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ 1
693#define EC_BYPASS_DUE_TO_REVERSED_2100HZ 2
694#define EC_BYPASS_RELEASED 3
695/*------------------------------------------------------------------*/
696/* function prototypes */
697/*------------------------------------------------------------------*/
698/*------------------------------------------------------------------*/
699#endif /* _INC_CAPI20 */
diff --git a/drivers/isdn/hardware/eicon/capidtmf.c b/drivers/isdn/hardware/eicon/capidtmf.c
new file mode 100644
index 000000000000..f130724144f3
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/capidtmf.c
@@ -0,0 +1,685 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26
27#include "platform.h"
28
29
30
31
32
33
34
35
36
37#include "capidtmf.h"
38
39/* #define TRACE_ */
40
41#define FILE_ "CAPIDTMF.C"
42
43/*---------------------------------------------------------------------------*/
44
45
46#define trace(a)
47
48
49
50/*---------------------------------------------------------------------------*/
51
52static short capidtmf_expand_table_alaw[0x0100] =
53{
54 -5504, 5504, -344, 344, -22016, 22016, -1376, 1376,
55 -2752, 2752, -88, 88, -11008, 11008, -688, 688,
56 -7552, 7552, -472, 472, -30208, 30208, -1888, 1888,
57 -3776, 3776, -216, 216, -15104, 15104, -944, 944,
58 -4480, 4480, -280, 280, -17920, 17920, -1120, 1120,
59 -2240, 2240, -24, 24, -8960, 8960, -560, 560,
60 -6528, 6528, -408, 408, -26112, 26112, -1632, 1632,
61 -3264, 3264, -152, 152, -13056, 13056, -816, 816,
62 -6016, 6016, -376, 376, -24064, 24064, -1504, 1504,
63 -3008, 3008, -120, 120, -12032, 12032, -752, 752,
64 -8064, 8064, -504, 504, -32256, 32256, -2016, 2016,
65 -4032, 4032, -248, 248, -16128, 16128, -1008, 1008,
66 -4992, 4992, -312, 312, -19968, 19968, -1248, 1248,
67 -2496, 2496, -56, 56, -9984, 9984, -624, 624,
68 -7040, 7040, -440, 440, -28160, 28160, -1760, 1760,
69 -3520, 3520, -184, 184, -14080, 14080, -880, 880,
70 -5248, 5248, -328, 328, -20992, 20992, -1312, 1312,
71 -2624, 2624, -72, 72, -10496, 10496, -656, 656,
72 -7296, 7296, -456, 456, -29184, 29184, -1824, 1824,
73 -3648, 3648, -200, 200, -14592, 14592, -912, 912,
74 -4224, 4224, -264, 264, -16896, 16896, -1056, 1056,
75 -2112, 2112, -8, 8, -8448, 8448, -528, 528,
76 -6272, 6272, -392, 392, -25088, 25088, -1568, 1568,
77 -3136, 3136, -136, 136, -12544, 12544, -784, 784,
78 -5760, 5760, -360, 360, -23040, 23040, -1440, 1440,
79 -2880, 2880, -104, 104, -11520, 11520, -720, 720,
80 -7808, 7808, -488, 488, -31232, 31232, -1952, 1952,
81 -3904, 3904, -232, 232, -15616, 15616, -976, 976,
82 -4736, 4736, -296, 296, -18944, 18944, -1184, 1184,
83 -2368, 2368, -40, 40, -9472, 9472, -592, 592,
84 -6784, 6784, -424, 424, -27136, 27136, -1696, 1696,
85 -3392, 3392, -168, 168, -13568, 13568, -848, 848
86};
87
88static short capidtmf_expand_table_ulaw[0x0100] =
89{
90 -32124, 32124, -1884, 1884, -7932, 7932, -372, 372,
91 -15996, 15996, -876, 876, -3900, 3900, -120, 120,
92 -23932, 23932, -1372, 1372, -5884, 5884, -244, 244,
93 -11900, 11900, -620, 620, -2876, 2876, -56, 56,
94 -28028, 28028, -1628, 1628, -6908, 6908, -308, 308,
95 -13948, 13948, -748, 748, -3388, 3388, -88, 88,
96 -19836, 19836, -1116, 1116, -4860, 4860, -180, 180,
97 -9852, 9852, -492, 492, -2364, 2364, -24, 24,
98 -30076, 30076, -1756, 1756, -7420, 7420, -340, 340,
99 -14972, 14972, -812, 812, -3644, 3644, -104, 104,
100 -21884, 21884, -1244, 1244, -5372, 5372, -212, 212,
101 -10876, 10876, -556, 556, -2620, 2620, -40, 40,
102 -25980, 25980, -1500, 1500, -6396, 6396, -276, 276,
103 -12924, 12924, -684, 684, -3132, 3132, -72, 72,
104 -17788, 17788, -988, 988, -4348, 4348, -148, 148,
105 -8828, 8828, -428, 428, -2108, 2108, -8, 8,
106 -31100, 31100, -1820, 1820, -7676, 7676, -356, 356,
107 -15484, 15484, -844, 844, -3772, 3772, -112, 112,
108 -22908, 22908, -1308, 1308, -5628, 5628, -228, 228,
109 -11388, 11388, -588, 588, -2748, 2748, -48, 48,
110 -27004, 27004, -1564, 1564, -6652, 6652, -292, 292,
111 -13436, 13436, -716, 716, -3260, 3260, -80, 80,
112 -18812, 18812, -1052, 1052, -4604, 4604, -164, 164,
113 -9340, 9340, -460, 460, -2236, 2236, -16, 16,
114 -29052, 29052, -1692, 1692, -7164, 7164, -324, 324,
115 -14460, 14460, -780, 780, -3516, 3516, -96, 96,
116 -20860, 20860, -1180, 1180, -5116, 5116, -196, 196,
117 -10364, 10364, -524, 524, -2492, 2492, -32, 32,
118 -24956, 24956, -1436, 1436, -6140, 6140, -260, 260,
119 -12412, 12412, -652, 652, -3004, 3004, -64, 64,
120 -16764, 16764, -924, 924, -4092, 4092, -132, 132,
121 -8316, 8316, -396, 396, -1980, 1980, 0, 0
122};
123
124
125/*---------------------------------------------------------------------------*/
126
127static short capidtmf_recv_window_function[CAPIDTMF_RECV_ACCUMULATE_CYCLES] =
128{
129 -500L, -999L, -1499L, -1998L, -2496L, -2994L, -3491L, -3988L,
130 -4483L, -4978L, -5471L, -5963L, -6454L, -6943L, -7431L, -7917L,
131 -8401L, -8883L, -9363L, -9840L, -10316L, -10789L, -11259L, -11727L,
132 -12193L, -12655L, -13115L, -13571L, -14024L, -14474L, -14921L, -15364L,
133 -15804L, -16240L, -16672L, -17100L, -17524L, -17944L, -18360L, -18772L,
134 -19180L, -19583L, -19981L, -20375L, -20764L, -21148L, -21527L, -21901L,
135 -22270L, -22634L, -22993L, -23346L, -23694L, -24037L, -24374L, -24705L,
136 -25030L, -25350L, -25664L, -25971L, -26273L, -26568L, -26858L, -27141L,
137 -27418L, -27688L, -27952L, -28210L, -28461L, -28705L, -28943L, -29174L,
138 -29398L, -29615L, -29826L, -30029L, -30226L, -30415L, -30598L, -30773L,
139 -30941L, -31102L, -31256L, -31402L, -31541L, -31673L, -31797L, -31914L,
140 -32024L, -32126L, -32221L, -32308L, -32388L, -32460L, -32524L, -32581L,
141 -32631L, -32673L, -32707L, -32734L, -32753L, -32764L, -32768L, -32764L,
142 -32753L, -32734L, -32707L, -32673L, -32631L, -32581L, -32524L, -32460L,
143 -32388L, -32308L, -32221L, -32126L, -32024L, -31914L, -31797L, -31673L,
144 -31541L, -31402L, -31256L, -31102L, -30941L, -30773L, -30598L, -30415L,
145 -30226L, -30029L, -29826L, -29615L, -29398L, -29174L, -28943L, -28705L,
146 -28461L, -28210L, -27952L, -27688L, -27418L, -27141L, -26858L, -26568L,
147 -26273L, -25971L, -25664L, -25350L, -25030L, -24705L, -24374L, -24037L,
148 -23694L, -23346L, -22993L, -22634L, -22270L, -21901L, -21527L, -21148L,
149 -20764L, -20375L, -19981L, -19583L, -19180L, -18772L, -18360L, -17944L,
150 -17524L, -17100L, -16672L, -16240L, -15804L, -15364L, -14921L, -14474L,
151 -14024L, -13571L, -13115L, -12655L, -12193L, -11727L, -11259L, -10789L,
152 -10316L, -9840L, -9363L, -8883L, -8401L, -7917L, -7431L, -6943L,
153 -6454L, -5963L, -5471L, -4978L, -4483L, -3988L, -3491L, -2994L,
154 -2496L, -1998L, -1499L, -999L, -500L,
155};
156
157static byte capidtmf_leading_zeroes_table[0x100] =
158{
159 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
160 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
161 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
162 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
163 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
164 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
165 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
166 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
167 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
168 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
169 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
170 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
172 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
173 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
174 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
175};
176
177#define capidtmf_byte_leading_zeroes(b) (capidtmf_leading_zeroes_table[(BYTE)(b)])
178#define capidtmf_word_leading_zeroes(w) (((w) & 0xff00) ? capidtmf_leading_zeroes_table[(w) >> 8] : 8 + capidtmf_leading_zeroes_table[(w)])
179#define capidtmf_dword_leading_zeroes(d) (((d) & 0xffff0000L) ? (((d) & 0xff000000L) ? capidtmf_leading_zeroes_table[(d) >> 24] : 8 + capidtmf_leading_zeroes_table[(d) >> 16]) : (((d) & 0xff00) ? 16 + capidtmf_leading_zeroes_table[(d) >> 8] : 24 + capidtmf_leading_zeroes_table[(d)]))
180
181
182/*---------------------------------------------------------------------------*/
183
184
185static void capidtmf_goertzel_loop (long *buffer, long *coeffs, short *sample, long count)
186{
187 int i, j;
188 long c, d, q0, q1, q2;
189
190 for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT - 1; i++)
191 {
192 q1 = buffer[i];
193 q2 = buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
194 d = coeffs[i] >> 1;
195 c = d << 1;
196 if (c >= 0)
197 {
198 for (j = 0; j < count; j++)
199 {
200 q0 = sample[j] - q2 + (c * (q1 >> 16)) + (((dword)(((dword) d) * ((dword)(q1 & 0xffff)))) >> 15);
201 q2 = q1;
202 q1 = q0;
203 }
204 }
205 else
206 {
207 c = -c;
208 d = -d;
209 for (j = 0; j < count; j++)
210 {
211 q0 = sample[j] - q2 - ((c * (q1 >> 16)) + (((dword)(((dword) d) * ((dword)(q1 & 0xffff)))) >> 15));
212 q2 = q1;
213 q1 = q0;
214 }
215 }
216 buffer[i] = q1;
217 buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] = q2;
218 }
219 q1 = buffer[i];
220 q2 = buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
221 c = (coeffs[i] >> 1) << 1;
222 if (c >= 0)
223 {
224 for (j = 0; j < count; j++)
225 {
226 q0 = sample[j] - q2 + (c * (q1 >> 16)) + (((dword)(((dword)(c >> 1)) * ((dword)(q1 & 0xffff)))) >> 15);
227 q2 = q1;
228 q1 = q0;
229 c -= CAPIDTMF_RECV_FUNDAMENTAL_DECREMENT;
230 }
231 }
232 else
233 {
234 c = -c;
235 for (j = 0; j < count; j++)
236 {
237 q0 = sample[j] - q2 - ((c * (q1 >> 16)) + (((dword)(((dword)(c >> 1)) * ((dword)(q1 & 0xffff)))) >> 15));
238 q2 = q1;
239 q1 = q0;
240 c += CAPIDTMF_RECV_FUNDAMENTAL_DECREMENT;
241 }
242 }
243 coeffs[i] = c;
244 buffer[i] = q1;
245 buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] = q2;
246}
247
248
249static void capidtmf_goertzel_result (long *buffer, long *coeffs)
250{
251 int i;
252 long d, e, q1, q2, lo, mid, hi;
253 dword k;
254
255 for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
256 {
257 q1 = buffer[i];
258 q2 = buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
259 d = coeffs[i] >> 1;
260 if (d >= 0)
261 d = ((d << 1) * (-q1 >> 16)) + (((dword)(((dword) d) * ((dword)(-q1 & 0xffff)))) >> 15);
262 else
263 d = ((-d << 1) * (-q1 >> 16)) + (((dword)(((dword) -d) * ((dword)(-q1 & 0xffff)))) >> 15);
264 e = (q2 >= 0) ? q2 : -q2;
265 if (d >= 0)
266 {
267 k = ((dword)(d & 0xffff)) * ((dword)(e & 0xffff));
268 lo = k & 0xffff;
269 mid = k >> 16;
270 k = ((dword)(d >> 16)) * ((dword)(e & 0xffff));
271 mid += k & 0xffff;
272 hi = k >> 16;
273 k = ((dword)(d & 0xffff)) * ((dword)(e >> 16));
274 mid += k & 0xffff;
275 hi += k >> 16;
276 hi += ((dword)(d >> 16)) * ((dword)(e >> 16));
277 }
278 else
279 {
280 d = -d;
281 k = ((dword)(d & 0xffff)) * ((dword)(e & 0xffff));
282 lo = -((long)(k & 0xffff));
283 mid = -((long)(k >> 16));
284 k = ((dword)(d >> 16)) * ((dword)(e & 0xffff));
285 mid -= k & 0xffff;
286 hi = -((long)(k >> 16));
287 k = ((dword)(d & 0xffff)) * ((dword)(e >> 16));
288 mid -= k & 0xffff;
289 hi -= k >> 16;
290 hi -= ((dword)(d >> 16)) * ((dword)(e >> 16));
291 }
292 if (q2 < 0)
293 {
294 lo = -lo;
295 mid = -mid;
296 hi = -hi;
297 }
298 d = (q1 >= 0) ? q1 : -q1;
299 k = ((dword)(d & 0xffff)) * ((dword)(d & 0xffff));
300 lo += k & 0xffff;
301 mid += k >> 16;
302 k = ((dword)(d >> 16)) * ((dword)(d & 0xffff));
303 mid += (k & 0xffff) << 1;
304 hi += (k >> 16) << 1;
305 hi += ((dword)(d >> 16)) * ((dword)(d >> 16));
306 d = (q2 >= 0) ? q2 : -q2;
307 k = ((dword)(d & 0xffff)) * ((dword)(d & 0xffff));
308 lo += k & 0xffff;
309 mid += k >> 16;
310 k = ((dword)(d >> 16)) * ((dword)(d & 0xffff));
311 mid += (k & 0xffff) << 1;
312 hi += (k >> 16) << 1;
313 hi += ((dword)(d >> 16)) * ((dword)(d >> 16));
314 mid += lo >> 16;
315 hi += mid >> 16;
316 buffer[i] = (lo & 0xffff) | (mid << 16);
317 buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] = hi;
318 }
319}
320
321
322/*---------------------------------------------------------------------------*/
323
324#define CAPIDTMF_RECV_GUARD_SNR_INDEX_697 0
325#define CAPIDTMF_RECV_GUARD_SNR_INDEX_770 1
326#define CAPIDTMF_RECV_GUARD_SNR_INDEX_852 2
327#define CAPIDTMF_RECV_GUARD_SNR_INDEX_941 3
328#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1209 4
329#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1336 5
330#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1477 6
331#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1633 7
332#define CAPIDTMF_RECV_GUARD_SNR_INDEX_635 8
333#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1010 9
334#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1140 10
335#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1272 11
336#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1405 12
337#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1555 13
338#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1715 14
339#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1875 15
340
341#define CAPIDTMF_RECV_GUARD_SNR_DONTCARE 0xc000
342#define CAPIDTMF_RECV_NO_DIGIT 0xff
343#define CAPIDTMF_RECV_TIME_GRANULARITY (CAPIDTMF_RECV_ACCUMULATE_CYCLES + 1)
344
345#define CAPIDTMF_RECV_INDICATION_DIGIT 0x0001
346
347static long capidtmf_recv_goertzel_coef_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] =
348{
349 0xda97L * 2, /* 697 Hz (Low group 697 Hz) */
350 0xd299L * 2, /* 770 Hz (Low group 770 Hz) */
351 0xc8cbL * 2, /* 852 Hz (Low group 852 Hz) */
352 0xbd36L * 2, /* 941 Hz (Low group 941 Hz) */
353 0x9501L * 2, /* 1209 Hz (High group 1209 Hz) */
354 0x7f89L * 2, /* 1336 Hz (High group 1336 Hz) */
355 0x6639L * 2, /* 1477 Hz (High group 1477 Hz) */
356 0x48c6L * 2, /* 1633 Hz (High group 1633 Hz) */
357 0xe14cL * 2, /* 630 Hz (Lower guard of low group 631 Hz) */
358 0xb2e0L * 2, /* 1015 Hz (Upper guard of low group 1039 Hz) */
359 0xa1a0L * 2, /* 1130 Hz (Lower guard of high group 1140 Hz) */
360 0x8a87L * 2, /* 1272 Hz (Guard between 1209 Hz and 1336 Hz: 1271 Hz) */
361 0x7353L * 2, /* 1405 Hz (2nd harmonics of 697 Hz and guard between 1336 Hz and 1477 Hz: 1405 Hz) */
362 0x583bL * 2, /* 1552 Hz (2nd harmonics of 770 Hz and guard between 1477 Hz and 1633 Hz: 1553 Hz) */
363 0x37d8L * 2, /* 1720 Hz (2nd harmonics of 852 Hz and upper guard of high group: 1715 Hz) */
364 0x0000L * 2 /* 100-630 Hz (fundamentals) */
365};
366
367
368static word capidtmf_recv_guard_snr_low_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] =
369{
370 14, /* Low group peak versus 697 Hz */
371 14, /* Low group peak versus 770 Hz */
372 16, /* Low group peak versus 852 Hz */
373 16, /* Low group peak versus 941 Hz */
374 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1209 Hz */
375 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1336 Hz */
376 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1477 Hz */
377 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1633 Hz */
378 14, /* Low group peak versus 635 Hz */
379 16, /* Low group peak versus 1010 Hz */
380 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1140 Hz */
381 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1272 Hz */
382 DSPDTMF_RX_HARMONICS_SEL_DEFAULT - 8, /* Low group peak versus 1405 Hz */
383 DSPDTMF_RX_HARMONICS_SEL_DEFAULT - 4, /* Low group peak versus 1555 Hz */
384 DSPDTMF_RX_HARMONICS_SEL_DEFAULT - 4, /* Low group peak versus 1715 Hz */
385 12 /* Low group peak versus 100-630 Hz */
386};
387
388
389static word capidtmf_recv_guard_snr_high_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] =
390{
391 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 697 Hz */
392 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 770 Hz */
393 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 852 Hz */
394 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 941 Hz */
395 20, /* High group peak versus 1209 Hz */
396 20, /* High group peak versus 1336 Hz */
397 20, /* High group peak versus 1477 Hz */
398 20, /* High group peak versus 1633 Hz */
399 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 635 Hz */
400 CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 1010 Hz */
401 16, /* High group peak versus 1140 Hz */
402 4, /* High group peak versus 1272 Hz */
403 6, /* High group peak versus 1405 Hz */
404 8, /* High group peak versus 1555 Hz */
405 16, /* High group peak versus 1715 Hz */
406 12 /* High group peak versus 100-630 Hz */
407};
408
409
410/*---------------------------------------------------------------------------*/
411
412static void capidtmf_recv_init (t_capidtmf_state *p_state)
413{
414 p_state->recv.min_gap_duration = 1;
415 p_state->recv.min_digit_duration = 1;
416
417 p_state->recv.cycle_counter = 0;
418 p_state->recv.current_digit_on_time = 0;
419 p_state->recv.current_digit_off_time = 0;
420 p_state->recv.current_digit_value = CAPIDTMF_RECV_NO_DIGIT;
421
422 p_state->recv.digit_write_pos = 0;
423 p_state->recv.digit_read_pos = 0;
424 p_state->recv.indication_state = 0;
425 p_state->recv.indication_state_ack = 0;
426 p_state->recv.state = CAPIDTMF_RECV_STATE_IDLE;
427}
428
429
430void capidtmf_recv_enable (t_capidtmf_state *p_state, word min_digit_duration, word min_gap_duration)
431{
432 p_state->recv.indication_state_ack &= CAPIDTMF_RECV_INDICATION_DIGIT;
433 p_state->recv.min_digit_duration = (word)(((((dword) min_digit_duration) * 8) +
434 ((dword)(CAPIDTMF_RECV_TIME_GRANULARITY / 2))) / ((dword) CAPIDTMF_RECV_TIME_GRANULARITY));
435 if (p_state->recv.min_digit_duration <= 1)
436 p_state->recv.min_digit_duration = 1;
437 else
438 (p_state->recv.min_digit_duration)--;
439 p_state->recv.min_gap_duration =
440 (word)((((dword) min_gap_duration) * 8) / ((dword) CAPIDTMF_RECV_TIME_GRANULARITY));
441 if (p_state->recv.min_gap_duration <= 1)
442 p_state->recv.min_gap_duration = 1;
443 else
444 (p_state->recv.min_gap_duration)--;
445 p_state->recv.state |= CAPIDTMF_RECV_STATE_DTMF_ACTIVE;
446}
447
448
449void capidtmf_recv_disable (t_capidtmf_state *p_state)
450{
451 p_state->recv.state &= ~CAPIDTMF_RECV_STATE_DTMF_ACTIVE;
452 if (p_state->recv.state == CAPIDTMF_RECV_STATE_IDLE)
453 capidtmf_recv_init (p_state);
454 else
455 {
456 p_state->recv.cycle_counter = 0;
457 p_state->recv.current_digit_on_time = 0;
458 p_state->recv.current_digit_off_time = 0;
459 p_state->recv.current_digit_value = CAPIDTMF_RECV_NO_DIGIT;
460 }
461}
462
463
464word capidtmf_recv_indication (t_capidtmf_state *p_state, byte *buffer)
465{
466 word i, j, k, flags;
467
468 flags = p_state->recv.indication_state ^ p_state->recv.indication_state_ack;
469 p_state->recv.indication_state_ack ^= flags & CAPIDTMF_RECV_INDICATION_DIGIT;
470 if (p_state->recv.digit_write_pos != p_state->recv.digit_read_pos)
471 {
472 i = 0;
473 k = p_state->recv.digit_write_pos;
474 j = p_state->recv.digit_read_pos;
475 do
476 {
477 buffer[i++] = p_state->recv.digit_buffer[j];
478 j = (j == CAPIDTMF_RECV_DIGIT_BUFFER_SIZE - 1) ? 0 : j + 1;
479 } while (j != k);
480 p_state->recv.digit_read_pos = k;
481 return (i);
482 }
483 p_state->recv.indication_state_ack ^= flags;
484 return (0);
485}
486
487
488#define CAPIDTMF_RECV_WINDOWED_SAMPLES 32
489
490void capidtmf_recv_block (t_capidtmf_state *p_state, byte *buffer, word length)
491{
492 byte result_digit;
493 word sample_number, cycle_counter, n, i;
494 word low_peak, high_peak;
495 dword lo, hi;
496 byte *p;
497 short *q;
498 byte goertzel_result_buffer[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
499 short windowed_sample_buffer[CAPIDTMF_RECV_WINDOWED_SAMPLES];
500
501
502 if (p_state->recv.state & CAPIDTMF_RECV_STATE_DTMF_ACTIVE)
503 {
504 cycle_counter = p_state->recv.cycle_counter;
505 sample_number = 0;
506 while (sample_number < length)
507 {
508 if (cycle_counter < CAPIDTMF_RECV_ACCUMULATE_CYCLES)
509 {
510 if (cycle_counter == 0)
511 {
512 for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
513 {
514 p_state->recv.goertzel_buffer[0][i] = 0;
515 p_state->recv.goertzel_buffer[1][i] = 0;
516 }
517 }
518 n = CAPIDTMF_RECV_ACCUMULATE_CYCLES - cycle_counter;
519 if (n > length - sample_number)
520 n = length - sample_number;
521 if (n > CAPIDTMF_RECV_WINDOWED_SAMPLES)
522 n = CAPIDTMF_RECV_WINDOWED_SAMPLES;
523 p = buffer + sample_number;
524 q = capidtmf_recv_window_function + cycle_counter;
525 if (p_state->ulaw)
526 {
527 for (i = 0; i < n; i++)
528 {
529 windowed_sample_buffer[i] =
530 (short)((capidtmf_expand_table_ulaw[p[i]] * ((long)(q[i]))) >> 15);
531 }
532 }
533 else
534 {
535 for (i = 0; i < n; i++)
536 {
537 windowed_sample_buffer[i] =
538 (short)((capidtmf_expand_table_alaw[p[i]] * ((long)(q[i]))) >> 15);
539 }
540 }
541 capidtmf_recv_goertzel_coef_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT - 1] = CAPIDTMF_RECV_FUNDAMENTAL_OFFSET;
542 capidtmf_goertzel_loop (p_state->recv.goertzel_buffer[0],
543 capidtmf_recv_goertzel_coef_table, windowed_sample_buffer, n);
544 cycle_counter += n;
545 sample_number += n;
546 }
547 else
548 {
549 capidtmf_goertzel_result (p_state->recv.goertzel_buffer[0],
550 capidtmf_recv_goertzel_coef_table);
551 for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
552 {
553 lo = (dword)(p_state->recv.goertzel_buffer[0][i]);
554 hi = (dword)(p_state->recv.goertzel_buffer[1][i]);
555 if (hi != 0)
556 {
557 n = capidtmf_dword_leading_zeroes (hi);
558 hi = (hi << n) | (lo >> (32 - n));
559 }
560 else
561 {
562 n = capidtmf_dword_leading_zeroes (lo);
563 hi = lo << n;
564 n += 32;
565 }
566 n = 195 - 3 * n;
567 if (hi >= 0xcb300000L)
568 n += 2;
569 else if (hi >= 0xa1450000L)
570 n++;
571 goertzel_result_buffer[i] = (byte) n;
572 }
573 low_peak = DSPDTMF_RX_SENSITIVITY_LOW_DEFAULT;
574 result_digit = CAPIDTMF_RECV_NO_DIGIT;
575 for (i = 0; i < CAPIDTMF_LOW_GROUP_FREQUENCIES; i++)
576 {
577 if (goertzel_result_buffer[i] > low_peak)
578 {
579 low_peak = goertzel_result_buffer[i];
580 result_digit = (byte) i;
581 }
582 }
583 high_peak = DSPDTMF_RX_SENSITIVITY_HIGH_DEFAULT;
584 n = CAPIDTMF_RECV_NO_DIGIT;
585 for (i = CAPIDTMF_LOW_GROUP_FREQUENCIES; i < CAPIDTMF_RECV_BASE_FREQUENCY_COUNT; i++)
586 {
587 if (goertzel_result_buffer[i] > high_peak)
588 {
589 high_peak = goertzel_result_buffer[i];
590 n = (i - CAPIDTMF_LOW_GROUP_FREQUENCIES) << 2;
591 }
592 }
593 result_digit |= (byte) n;
594 if (low_peak + DSPDTMF_RX_HIGH_EXCEEDING_LOW_DEFAULT < high_peak)
595 result_digit = CAPIDTMF_RECV_NO_DIGIT;
596 if (high_peak + DSPDTMF_RX_LOW_EXCEEDING_HIGH_DEFAULT < low_peak)
597 result_digit = CAPIDTMF_RECV_NO_DIGIT;
598 n = 0;
599 for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
600 {
601 if ((((short)(low_peak - goertzel_result_buffer[i] - capidtmf_recv_guard_snr_low_table[i])) < 0)
602 || (((short)(high_peak - goertzel_result_buffer[i] - capidtmf_recv_guard_snr_high_table[i])) < 0))
603 {
604 n++;
605 }
606 }
607 if (n != 2)
608 result_digit = CAPIDTMF_RECV_NO_DIGIT;
609
610 if (result_digit == CAPIDTMF_RECV_NO_DIGIT)
611 {
612 if (p_state->recv.current_digit_on_time != 0)
613 {
614 if (++(p_state->recv.current_digit_off_time) >= p_state->recv.min_gap_duration)
615 {
616 p_state->recv.current_digit_on_time = 0;
617 p_state->recv.current_digit_off_time = 0;
618 }
619 }
620 else
621 {
622 if (p_state->recv.current_digit_off_time != 0)
623 (p_state->recv.current_digit_off_time)--;
624 }
625 }
626 else
627 {
628 if ((p_state->recv.current_digit_on_time == 0)
629 && (p_state->recv.current_digit_off_time != 0))
630 {
631 (p_state->recv.current_digit_off_time)--;
632 }
633 else
634 {
635 n = p_state->recv.current_digit_off_time;
636 if ((p_state->recv.current_digit_on_time != 0)
637 && (result_digit != p_state->recv.current_digit_value))
638 {
639 p_state->recv.current_digit_on_time = 0;
640 n = 0;
641 }
642 p_state->recv.current_digit_value = result_digit;
643 p_state->recv.current_digit_off_time = 0;
644 if (p_state->recv.current_digit_on_time != 0xffff)
645 {
646 p_state->recv.current_digit_on_time += n + 1;
647 if (p_state->recv.current_digit_on_time >= p_state->recv.min_digit_duration)
648 {
649 p_state->recv.current_digit_on_time = 0xffff;
650 i = (p_state->recv.digit_write_pos == CAPIDTMF_RECV_DIGIT_BUFFER_SIZE - 1) ?
651 0 : p_state->recv.digit_write_pos + 1;
652 if (i == p_state->recv.digit_read_pos)
653 {
654 trace (dprintf ("%s,%d: Receive digit overrun",
655 (char *)(FILE_), __LINE__));
656 }
657 else
658 {
659 p_state->recv.digit_buffer[p_state->recv.digit_write_pos] = result_digit;
660 p_state->recv.digit_write_pos = i;
661 p_state->recv.indication_state =
662 (p_state->recv.indication_state & ~CAPIDTMF_RECV_INDICATION_DIGIT) |
663 (~p_state->recv.indication_state_ack & CAPIDTMF_RECV_INDICATION_DIGIT);
664 }
665 }
666 }
667 }
668 }
669 cycle_counter = 0;
670 sample_number++;
671 }
672 }
673 p_state->recv.cycle_counter = cycle_counter;
674 }
675}
676
677
678void capidtmf_init (t_capidtmf_state *p_state, byte ulaw)
679{
680 p_state->ulaw = ulaw;
681 capidtmf_recv_init (p_state);
682}
683
684
685/*---------------------------------------------------------------------------*/
diff --git a/drivers/isdn/hardware/eicon/capidtmf.h b/drivers/isdn/hardware/eicon/capidtmf.h
new file mode 100644
index 000000000000..242048fb2dd7
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/capidtmf.h
@@ -0,0 +1,79 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef CAPIDTMF_H_
27#define CAPIDTMF_H_
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30#define CAPIDTMF_TONE_GROUP_COUNT 2
31#define CAPIDTMF_LOW_GROUP_FREQUENCIES 4
32#define CAPIDTMF_HIGH_GROUP_FREQUENCIES 4
33#define DSPDTMF_RX_SENSITIVITY_LOW_DEFAULT 50 /* -52 dBm */
34#define DSPDTMF_RX_SENSITIVITY_HIGH_DEFAULT 50 /* -52 dBm */
35#define DSPDTMF_RX_HIGH_EXCEEDING_LOW_DEFAULT 10 /* dB */
36#define DSPDTMF_RX_LOW_EXCEEDING_HIGH_DEFAULT 10 /* dB */
37#define DSPDTMF_RX_HARMONICS_SEL_DEFAULT 12 /* dB */
38#define CAPIDTMF_RECV_BASE_FREQUENCY_COUNT (CAPIDTMF_LOW_GROUP_FREQUENCIES + CAPIDTMF_HIGH_GROUP_FREQUENCIES)
39#define CAPIDTMF_RECV_GUARD_FREQUENCY_COUNT 8
40#define CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT (CAPIDTMF_RECV_BASE_FREQUENCY_COUNT + CAPIDTMF_RECV_GUARD_FREQUENCY_COUNT)
41#define CAPIDTMF_RECV_POSITIVE_COEFF_COUNT 16
42#define CAPIDTMF_RECV_NEGATIVE_COEFF_COUNT (CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT - CAPIDTMF_RECV_POSITIVE_COEFF_COUNT)
43#define CAPIDTMF_RECV_ACCUMULATE_CYCLES 205
44#define CAPIDTMF_RECV_FUNDAMENTAL_OFFSET (0xff35L * 2)
45#define CAPIDTMF_RECV_FUNDAMENTAL_DECREMENT (0x0028L * 2)
46#define CAPIDTMF_RECV_DIGIT_BUFFER_SIZE 32
47#define CAPIDTMF_RECV_STATE_IDLE 0x00
48#define CAPIDTMF_RECV_STATE_DTMF_ACTIVE 0x01
49typedef struct tag_capidtmf_recv_state
50{
51 byte digit_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE];
52 word digit_write_pos;
53 word digit_read_pos;
54 word indication_state;
55 word indication_state_ack;
56 long goertzel_buffer[2][CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
57 word min_gap_duration;
58 word min_digit_duration;
59 word cycle_counter;
60 word current_digit_on_time;
61 word current_digit_off_time;
62 byte current_digit_value;
63 byte state;
64} t_capidtmf_recv_state;
65typedef struct tag_capidtmf_state
66{
67 byte ulaw;
68 t_capidtmf_recv_state recv;
69} t_capidtmf_state;
70word capidtmf_recv_indication (t_capidtmf_state *p_state, byte *buffer);
71void capidtmf_recv_block (t_capidtmf_state *p_state, byte *buffer, word length);
72void capidtmf_init (t_capidtmf_state *p_state, byte ulaw);
73void capidtmf_recv_enable (t_capidtmf_state *p_state, word min_digit_duration, word min_gap_duration);
74void capidtmf_recv_disable (t_capidtmf_state *p_state);
75#define capidtmf_indication(p_state,buffer) (((p_state)->recv.indication_state != (p_state)->recv.indication_state_ack) ? capidtmf_recv_indication (p_state, buffer) : 0)
76#define capidtmf_recv_process_block(p_state,buffer,length) { if ((p_state)->recv.state != CAPIDTMF_RECV_STATE_IDLE) capidtmf_recv_block (p_state, buffer, length); }
77/*---------------------------------------------------------------------------*/
78/*---------------------------------------------------------------------------*/
79#endif
diff --git a/drivers/isdn/hardware/eicon/capifunc.c b/drivers/isdn/hardware/eicon/capifunc.c
new file mode 100644
index 000000000000..0afd7633556d
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/capifunc.c
@@ -0,0 +1,1219 @@
1/* $Id: capifunc.c,v 1.61.4.7 2005/02/11 19:40:25 armin Exp $
2 *
3 * ISDN interface module for Eicon active cards DIVA.
4 * CAPI Interface common functions
5 *
6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 */
13
14#include "platform.h"
15#include "os_capi.h"
16#include "di_defs.h"
17#include "capi20.h"
18#include "divacapi.h"
19#include "divasync.h"
20#include "capifunc.h"
21
22#define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR)
23#define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG)
24
25DIVA_CAPI_ADAPTER *adapter = (DIVA_CAPI_ADAPTER *) NULL;
26APPL *application = (APPL *) NULL;
27byte max_appl = MAX_APPL;
28byte max_adapter = 0;
29static CAPI_MSG *mapped_msg = (CAPI_MSG *) NULL;
30
31byte UnMapController(byte);
32char DRIVERRELEASE_CAPI[32];
33
34extern void AutomaticLaw(DIVA_CAPI_ADAPTER *);
35extern void callback(ENTITY *);
36extern word api_remove_start(void);
37extern word CapiRelease(word);
38extern word CapiRegister(word);
39extern word api_put(APPL *, CAPI_MSG *);
40
41static diva_os_spin_lock_t api_lock;
42
43static LIST_HEAD(cards);
44
45static dword notify_handle;
46static void DIRequest(ENTITY * e);
47static DESCRIPTOR MAdapter;
48static DESCRIPTOR DAdapter;
49static byte ControllerMap[MAX_DESCRIPTORS + 1];
50
51
52static void diva_register_appl(struct capi_ctr *, __u16,
53 capi_register_params *);
54static void diva_release_appl(struct capi_ctr *, __u16);
55static char *diva_procinfo(struct capi_ctr *);
56static u16 diva_send_message(struct capi_ctr *,
57 diva_os_message_buffer_s *);
58extern void diva_os_set_controller_struct(struct capi_ctr *);
59
60extern void DIVA_DIDD_Read(DESCRIPTOR *, int);
61
62/*
63 * debug
64 */
65static void no_printf(unsigned char *, ...);
66#include "debuglib.c"
67static void xlog(char *x, ...)
68{
69#ifndef DIVA_NO_DEBUGLIB
70 va_list ap;
71 if (myDriverDebugHandle.dbgMask & DL_XLOG) {
72 va_start(ap, x);
73 if (myDriverDebugHandle.dbg_irq) {
74 myDriverDebugHandle.dbg_irq(myDriverDebugHandle.id,
75 DLI_XLOG, x, ap);
76 } else if (myDriverDebugHandle.dbg_old) {
77 myDriverDebugHandle.dbg_old(myDriverDebugHandle.id,
78 x, ap);
79 }
80 va_end(ap);
81 }
82#endif
83}
84
85/*
86 * info for proc
87 */
88static char *diva_procinfo(struct capi_ctr *ctrl)
89{
90 return (ctrl->serial);
91}
92
93/*
94 * stop debugging
95 */
96static void stop_dbg(void)
97{
98 DbgDeregister();
99 memset(&MAdapter, 0, sizeof(MAdapter));
100 dprintf = no_printf;
101}
102
103/*
104 * dummy debug function
105 */
106static void no_printf(unsigned char *x, ...)
107{
108}
109
110/*
111 * Controller mapping
112 */
113byte MapController(byte Controller)
114{
115 byte i;
116 byte MappedController = 0;
117 byte ctrl = Controller & 0x7f; /* mask external controller bit off */
118
119 for (i = 1; i < max_adapter + 1; i++) {
120 if (ctrl == ControllerMap[i]) {
121 MappedController = (byte) i;
122 break;
123 }
124 }
125 if (i > max_adapter) {
126 ControllerMap[0] = ctrl;
127 MappedController = 0;
128 }
129 return (MappedController | (Controller & 0x80)); /* put back external controller bit */
130}
131
132/*
133 * Controller unmapping
134 */
135byte UnMapController(byte MappedController)
136{
137 byte Controller;
138 byte ctrl = MappedController & 0x7f; /* mask external controller bit off */
139
140 if (ctrl <= max_adapter) {
141 Controller = ControllerMap[ctrl];
142 } else {
143 Controller = 0;
144 }
145
146 return (Controller | (MappedController & 0x80)); /* put back external controller bit */
147}
148
149/*
150 * find a new free id
151 */
152static int find_free_id(void)
153{
154 int num = 0;
155 DIVA_CAPI_ADAPTER *a;
156
157 while (num < MAX_DESCRIPTORS) {
158 a = &adapter[num];
159 if (!a->Id)
160 break;
161 num++;
162 }
163 return(num + 1);
164}
165
166/*
167 * find a card structure by controller number
168 */
169static diva_card *find_card_by_ctrl(word controller)
170{
171 struct list_head *tmp;
172 diva_card *card;
173
174 list_for_each(tmp, &cards) {
175 card = list_entry(tmp, diva_card, list);
176 if (ControllerMap[card->Id] == controller) {
177 if (card->remove_in_progress)
178 card = NULL;
179 return(card);
180 }
181 }
182 return (diva_card *) 0;
183}
184
185/*
186 * Buffer RX/TX
187 */
188void *TransmitBufferSet(APPL * appl, dword ref)
189{
190 appl->xbuffer_used[ref] = TRUE;
191 DBG_PRV1(("%d:xbuf_used(%d)", appl->Id, ref + 1))
192 return (void *) ref;
193}
194
195void *TransmitBufferGet(APPL * appl, void *p)
196{
197 if (appl->xbuffer_internal[(dword) p])
198 return appl->xbuffer_internal[(dword) p];
199
200 return appl->xbuffer_ptr[(dword) p];
201}
202
203void TransmitBufferFree(APPL * appl, void *p)
204{
205 appl->xbuffer_used[(dword) p] = FALSE;
206 DBG_PRV1(("%d:xbuf_free(%d)", appl->Id, ((dword) p) + 1))
207}
208
209void *ReceiveBufferGet(APPL * appl, int Num)
210{
211 return &appl->ReceiveBuffer[Num * appl->MaxDataLength];
212}
213
214/*
215 * api_remove_start/complete for cleanup
216 */
217void api_remove_complete(void)
218{
219 DBG_PRV1(("api_remove_complete"))
220}
221
222/*
223 * main function called by message.c
224 */
225void sendf(APPL * appl, word command, dword Id, word Number, byte * format, ...)
226{
227 word i, j;
228 word length = 12, dlength = 0;
229 byte *write;
230 CAPI_MSG msg;
231 byte *string = NULL;
232 va_list ap;
233 diva_os_message_buffer_s *dmb;
234 diva_card *card = NULL;
235 dword tmp;
236
237 if (!appl)
238 return;
239
240 DBG_PRV1(("sendf(a=%d,cmd=%x,format=%s)",
241 appl->Id, command, (byte *) format))
242
243 PUT_WORD(&msg.header.appl_id, appl->Id);
244 PUT_WORD(&msg.header.command, command);
245 if ((byte) (command >> 8) == 0x82)
246 Number = appl->Number++;
247 PUT_WORD(&msg.header.number, Number);
248
249 PUT_DWORD(&msg.header.controller, Id);
250 write = (byte *) & msg;
251 write += 12;
252
253 va_start(ap, format);
254 for (i = 0; format[i]; i++) {
255 switch (format[i]) {
256 case 'b':
257 tmp = va_arg(ap, dword);
258 *(byte *) write = (byte) (tmp & 0xff);
259 write += 1;
260 length += 1;
261 break;
262 case 'w':
263 tmp = va_arg(ap, dword);
264 PUT_WORD(write, (tmp & 0xffff));
265 write += 2;
266 length += 2;
267 break;
268 case 'd':
269 tmp = va_arg(ap, dword);
270 PUT_DWORD(write, tmp);
271 write += 4;
272 length += 4;
273 break;
274 case 's':
275 case 'S':
276 string = va_arg(ap, byte *);
277 length += string[0] + 1;
278 for (j = 0; j <= string[0]; j++)
279 *write++ = string[j];
280 break;
281 }
282 }
283 va_end(ap);
284
285 PUT_WORD(&msg.header.length, length);
286 msg.header.controller = UnMapController(msg.header.controller);
287
288 if (command == _DATA_B3_I)
289 dlength = GET_WORD(
290 ((byte *) & msg.info.data_b3_ind.Data_Length));
291
292 if (!(dmb = diva_os_alloc_message_buffer(length + dlength,
293 (void **) &write))) {
294 DBG_ERR(("sendf: alloc_message_buffer failed, incoming msg dropped."))
295 return;
296 }
297
298 /* copy msg header to sk_buff */
299 memcpy(write, (byte *) & msg, length);
300
301 /* if DATA_B3_IND, copy data too */
302 if (command == _DATA_B3_I) {
303 dword data = GET_DWORD(&msg.info.data_b3_ind.Data);
304 memcpy(write + length, (void *) data, dlength);
305 }
306
307#ifndef DIVA_NO_DEBUGLIB
308 if (myDriverDebugHandle.dbgMask & DL_XLOG) {
309 switch (command) {
310 default:
311 xlog("\x00\x02", &msg, 0x81, length);
312 break;
313 case _DATA_B3_R | CONFIRM:
314 if (myDriverDebugHandle.dbgMask & DL_BLK)
315 xlog("\x00\x02", &msg, 0x81, length);
316 break;
317 case _DATA_B3_I:
318 if (myDriverDebugHandle.dbgMask & DL_BLK) {
319 xlog("\x00\x02", &msg, 0x81, length);
320 for (i = 0; i < dlength; i += 256) {
321 DBG_BLK((((char *) GET_DWORD(&msg.info.data_b3_ind.Data)) + i,
322 ((dlength - i) < 256) ? (dlength - i) : 256))
323 if (!(myDriverDebugHandle.dbgMask & DL_PRV0))
324 break; /* not more if not explicitely requested */
325 }
326 }
327 break;
328 }
329 }
330#endif
331
332 /* find the card structure for this controller */
333 if (!(card = find_card_by_ctrl(write[8] & 0x7f))) {
334 DBG_ERR(("sendf - controller %d not found, incoming msg dropped",
335 write[8] & 0x7f))
336 diva_os_free_message_buffer(dmb);
337 return;
338 }
339 /* send capi msg to capi layer */
340 capi_ctr_handle_message(&card->capi_ctrl, appl->Id, dmb);
341}
342
343/*
344 * cleanup adapter
345 */
346static void clean_adapter(int id, struct list_head *free_mem_q)
347{
348 DIVA_CAPI_ADAPTER *a;
349 int i, k;
350
351 a = &adapter[id];
352 k = li_total_channels - a->li_channels;
353 if (k == 0) {
354 if (li_config_table) {
355 list_add((struct list_head *)li_config_table, free_mem_q);
356 li_config_table = NULL;
357 }
358 } else {
359 if (a->li_base < k) {
360 memmove(&li_config_table[a->li_base],
361 &li_config_table[a->li_base + a->li_channels],
362 (k - a->li_base) * sizeof(LI_CONFIG));
363 for (i = 0; i < k; i++) {
364 memmove(&li_config_table[i].flag_table[a->li_base],
365 &li_config_table[i].flag_table[a->li_base + a->li_channels],
366 k - a->li_base);
367 memmove(&li_config_table[i].
368 coef_table[a->li_base],
369 &li_config_table[i].coef_table[a->li_base + a->li_channels],
370 k - a->li_base);
371 }
372 }
373 }
374 li_total_channels = k;
375 for (i = id; i < max_adapter; i++) {
376 if (adapter[i].request)
377 adapter[i].li_base -= a->li_channels;
378 }
379 if (a->plci)
380 list_add((struct list_head *)a->plci, free_mem_q);
381
382 memset(a, 0x00, sizeof(DIVA_CAPI_ADAPTER));
383 while ((max_adapter != 0) && !adapter[max_adapter - 1].request)
384 max_adapter--;
385}
386
387/*
388 * remove a card, but ensures consistent state of LI tables
389 * in the time adapter is removed
390 */
391static void divacapi_remove_card(DESCRIPTOR * d)
392{
393 diva_card *card = NULL;
394 diva_os_spin_lock_magic_t old_irql;
395 LIST_HEAD(free_mem_q);
396 struct list_head *link;
397 struct list_head *tmp;
398
399 /*
400 * Set "remove in progress flag".
401 * Ensures that there is no call from sendf to CAPI in
402 * the time CAPI controller is about to be removed.
403 */
404 diva_os_enter_spin_lock(&api_lock, &old_irql, "remove card");
405 list_for_each(tmp, &cards) {
406 card = list_entry(tmp, diva_card, list);
407 if (card->d.request == d->request) {
408 card->remove_in_progress = 1;
409 list_del(tmp);
410 break;
411 }
412 }
413 diva_os_leave_spin_lock(&api_lock, &old_irql, "remove card");
414
415 if (card) {
416 /*
417 * Detach CAPI. Sendf cannot call to CAPI any more.
418 * After detach no call to send_message() is done too.
419 */
420 detach_capi_ctr(&card->capi_ctrl);
421
422 /*
423 * Now get API lock (to ensure stable state of LI tables)
424 * and update the adapter map/LI table.
425 */
426 diva_os_enter_spin_lock(&api_lock, &old_irql, "remove card");
427
428 clean_adapter(card->Id - 1, &free_mem_q);
429 DBG_TRC(("DelAdapterMap (%d) -> (%d)",
430 ControllerMap[card->Id], card->Id))
431 ControllerMap[card->Id] = 0;
432 DBG_TRC(("adapter remove, max_adapter=%d",
433 max_adapter));
434 diva_os_leave_spin_lock(&api_lock, &old_irql, "remove card");
435
436 /* After releasing the lock, we can free the memory */
437 diva_os_free (0, card);
438 }
439
440 /* free queued memory areas */
441 list_for_each_safe(link, tmp, &free_mem_q) {
442 list_del(link);
443 diva_os_free(0, link);
444 }
445}
446
447/*
448 * remove cards
449 */
450static void divacapi_remove_cards(void)
451{
452 DESCRIPTOR d;
453 struct list_head *tmp;
454 diva_card *card;
455 diva_os_spin_lock_magic_t old_irql;
456
457rescan:
458 diva_os_enter_spin_lock(&api_lock, &old_irql, "remove cards");
459 list_for_each(tmp, &cards) {
460 card = list_entry(tmp, diva_card, list);
461 diva_os_leave_spin_lock(&api_lock, &old_irql, "remove cards");
462 d.request = card->d.request;
463 divacapi_remove_card(&d);
464 goto rescan;
465 }
466 diva_os_leave_spin_lock(&api_lock, &old_irql, "remove cards");
467}
468
469/*
470 * sync_callback
471 */
472static void sync_callback(ENTITY * e)
473{
474 diva_os_spin_lock_magic_t old_irql;
475
476 DBG_TRC(("cb:Id=%x,Rc=%x,Ind=%x", e->Id, e->Rc, e->Ind))
477
478 diva_os_enter_spin_lock(&api_lock, &old_irql, "sync_callback");
479 callback(e);
480 diva_os_leave_spin_lock(&api_lock, &old_irql, "sync_callback");
481}
482
483/*
484 * add a new card
485 */
486static int diva_add_card(DESCRIPTOR * d)
487{
488 int k = 0, i = 0;
489 diva_os_spin_lock_magic_t old_irql;
490 diva_card *card = NULL;
491 struct capi_ctr *ctrl = NULL;
492 DIVA_CAPI_ADAPTER *a = NULL;
493 IDI_SYNC_REQ sync_req;
494 char serial[16];
495 void* mem_to_free;
496 LI_CONFIG *new_li_config_table;
497 int j;
498
499 if (!(card = (diva_card *) diva_os_malloc(0, sizeof(diva_card)))) {
500 DBG_ERR(("diva_add_card: failed to allocate card struct."))
501 return (0);
502 }
503 memset((char *) card, 0x00, sizeof(diva_card));
504 memcpy(&card->d, d, sizeof(DESCRIPTOR));
505 sync_req.GetName.Req = 0;
506 sync_req.GetName.Rc = IDI_SYNC_REQ_GET_NAME;
507 card->d.request((ENTITY *) & sync_req);
508 strlcpy(card->name, sync_req.GetName.name, sizeof(card->name));
509 ctrl = &card->capi_ctrl;
510 strcpy(ctrl->name, card->name);
511 ctrl->register_appl = diva_register_appl;
512 ctrl->release_appl = diva_release_appl;
513 ctrl->send_message = diva_send_message;
514 ctrl->procinfo = diva_procinfo;
515 ctrl->driverdata = card;
516 diva_os_set_controller_struct(ctrl);
517
518 if (attach_capi_ctr(ctrl)) {
519 DBG_ERR(("diva_add_card: failed to attach controller."))
520 diva_os_free(0, card);
521 return (0);
522 }
523
524 diva_os_enter_spin_lock(&api_lock, &old_irql, "find id");
525 card->Id = find_free_id();
526 diva_os_leave_spin_lock(&api_lock, &old_irql, "find id");
527
528 strlcpy(ctrl->manu, M_COMPANY, sizeof(ctrl->manu));
529 ctrl->version.majorversion = 2;
530 ctrl->version.minorversion = 0;
531 ctrl->version.majormanuversion = DRRELMAJOR;
532 ctrl->version.minormanuversion = DRRELMINOR;
533 sync_req.GetSerial.Req = 0;
534 sync_req.GetSerial.Rc = IDI_SYNC_REQ_GET_SERIAL;
535 sync_req.GetSerial.serial = 0;
536 card->d.request((ENTITY *) & sync_req);
537 if ((i = ((sync_req.GetSerial.serial & 0xff000000) >> 24))) {
538 sprintf(serial, "%ld-%d",
539 sync_req.GetSerial.serial & 0x00ffffff, i + 1);
540 } else {
541 sprintf(serial, "%ld", sync_req.GetSerial.serial);
542 }
543 serial[CAPI_SERIAL_LEN - 1] = 0;
544 strlcpy(ctrl->serial, serial, sizeof(ctrl->serial));
545
546 a = &adapter[card->Id - 1];
547 card->adapter = a;
548 a->os_card = card;
549 ControllerMap[card->Id] = (byte) (ctrl->cnr);
550
551 DBG_TRC(("AddAdapterMap (%d) -> (%d)", ctrl->cnr, card->Id))
552
553 sync_req.xdi_capi_prms.Req = 0;
554 sync_req.xdi_capi_prms.Rc = IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS;
555 sync_req.xdi_capi_prms.info.structure_length =
556 sizeof(diva_xdi_get_capi_parameters_t);
557 card->d.request((ENTITY *) & sync_req);
558 a->flag_dynamic_l1_down =
559 sync_req.xdi_capi_prms.info.flag_dynamic_l1_down;
560 a->group_optimization_enabled =
561 sync_req.xdi_capi_prms.info.group_optimization_enabled;
562 a->request = DIRequest; /* card->d.request; */
563 a->max_plci = card->d.channels + 30;
564 a->max_listen = (card->d.channels > 2) ? 8 : 2;
565 if (!
566 (a->plci =
567 (PLCI *) diva_os_malloc(0, sizeof(PLCI) * a->max_plci))) {
568 DBG_ERR(("diva_add_card: failed alloc plci struct."))
569 memset(a, 0, sizeof(DIVA_CAPI_ADAPTER));
570 return (0);
571 }
572 memset(a->plci, 0, sizeof(PLCI) * a->max_plci);
573
574 for (k = 0; k < a->max_plci; k++) {
575 a->Id = (byte) card->Id;
576 a->plci[k].Sig.callback = sync_callback;
577 a->plci[k].Sig.XNum = 1;
578 a->plci[k].Sig.X = a->plci[k].XData;
579 a->plci[k].Sig.user[0] = (word) (card->Id - 1);
580 a->plci[k].Sig.user[1] = (word) k;
581 a->plci[k].NL.callback = sync_callback;
582 a->plci[k].NL.XNum = 1;
583 a->plci[k].NL.X = a->plci[k].XData;
584 a->plci[k].NL.user[0] = (word) ((card->Id - 1) | 0x8000);
585 a->plci[k].NL.user[1] = (word) k;
586 a->plci[k].adapter = a;
587 }
588
589 a->profile.Number = card->Id;
590 a->profile.Channels = card->d.channels;
591 if (card->d.features & DI_FAX3) {
592 a->profile.Global_Options = 0x71;
593 if (card->d.features & DI_CODEC)
594 a->profile.Global_Options |= 0x6;
595#if IMPLEMENT_DTMF
596 a->profile.Global_Options |= 0x8;
597#endif /* IMPLEMENT_DTMF */
598 a->profile.Global_Options |= 0x80; /* Line Interconnect */
599#if IMPLEMENT_ECHO_CANCELLER
600 a->profile.Global_Options |= 0x100;
601#endif /* IMPLEMENT_ECHO_CANCELLER */
602 a->profile.B1_Protocols = 0xdf;
603 a->profile.B2_Protocols = 0x1fdb;
604 a->profile.B3_Protocols = 0xb7;
605 a->manufacturer_features = MANUFACTURER_FEATURE_HARDDTMF;
606 } else {
607 a->profile.Global_Options = 0x71;
608 if (card->d.features & DI_CODEC)
609 a->profile.Global_Options |= 0x2;
610 a->profile.B1_Protocols = 0x43;
611 a->profile.B2_Protocols = 0x1f0f;
612 a->profile.B3_Protocols = 0x07;
613 a->manufacturer_features = 0;
614 }
615
616 a->li_pri = (a->profile.Channels > 2);
617 a->li_channels = a->li_pri ? MIXER_CHANNELS_PRI : MIXER_CHANNELS_BRI;
618 a->li_base = 0;
619 for (i = 0; &adapter[i] != a; i++) {
620 if (adapter[i].request)
621 a->li_base = adapter[i].li_base + adapter[i].li_channels;
622 }
623 k = li_total_channels + a->li_channels;
624 new_li_config_table =
625 (LI_CONFIG *) diva_os_malloc(0, ((k * sizeof(LI_CONFIG) + 3) & ~3) + (2 * k) * ((k + 3) & ~3));
626 if (new_li_config_table == NULL) {
627 DBG_ERR(("diva_add_card: failed alloc li_config table."))
628 memset(a, 0, sizeof(DIVA_CAPI_ADAPTER));
629 return (0);
630 }
631
632 /* Prevent access to line interconnect table in process update */
633 diva_os_enter_spin_lock(&api_lock, &old_irql, "add card");
634
635 j = 0;
636 for (i = 0; i < k; i++) {
637 if ((i >= a->li_base) && (i < a->li_base + a->li_channels))
638 memset(&new_li_config_table[i], 0, sizeof(LI_CONFIG));
639 else
640 memcpy(&new_li_config_table[i], &li_config_table[j], sizeof(LI_CONFIG));
641 new_li_config_table[i].flag_table =
642 ((byte *) new_li_config_table) + (((k * sizeof(LI_CONFIG) + 3) & ~3) + (2 * i) * ((k + 3) & ~3));
643 new_li_config_table[i].coef_table =
644 ((byte *) new_li_config_table) + (((k * sizeof(LI_CONFIG) + 3) & ~3) + (2 * i + 1) * ((k + 3) & ~3));
645 if ((i >= a->li_base) && (i < a->li_base + a->li_channels)) {
646 new_li_config_table[i].adapter = a;
647 memset(&new_li_config_table[i].flag_table[0], 0, k);
648 memset(&new_li_config_table[i].coef_table[0], 0, k);
649 } else {
650 if (a->li_base != 0) {
651 memcpy(&new_li_config_table[i].flag_table[0],
652 &li_config_table[j].flag_table[0],
653 a->li_base);
654 memcpy(&new_li_config_table[i].coef_table[0],
655 &li_config_table[j].coef_table[0],
656 a->li_base);
657 }
658 memset(&new_li_config_table[i].flag_table[a->li_base], 0, a->li_channels);
659 memset(&new_li_config_table[i].coef_table[a->li_base], 0, a->li_channels);
660 if (a->li_base + a->li_channels < k) {
661 memcpy(&new_li_config_table[i].flag_table[a->li_base +
662 a->li_channels],
663 &li_config_table[j].flag_table[a->li_base],
664 k - (a->li_base + a->li_channels));
665 memcpy(&new_li_config_table[i].coef_table[a->li_base +
666 a->li_channels],
667 &li_config_table[j].coef_table[a->li_base],
668 k - (a->li_base + a->li_channels));
669 }
670 j++;
671 }
672 }
673 li_total_channels = k;
674
675 mem_to_free = li_config_table;
676
677 li_config_table = new_li_config_table;
678 for (i = card->Id; i < max_adapter; i++) {
679 if (adapter[i].request)
680 adapter[i].li_base += a->li_channels;
681 }
682
683 if (a == &adapter[max_adapter])
684 max_adapter++;
685
686 list_add(&(card->list), &cards);
687 AutomaticLaw(a);
688
689 diva_os_leave_spin_lock(&api_lock, &old_irql, "add card");
690
691 if (mem_to_free) {
692 diva_os_free (0, mem_to_free);
693 }
694
695 i = 0;
696 while (i++ < 30) {
697 if (a->automatic_law > 3)
698 break;
699 diva_os_sleep(10);
700 }
701
702 /* profile information */
703 PUT_WORD(&ctrl->profile.nbchannel, card->d.channels);
704 ctrl->profile.goptions = a->profile.Global_Options;
705 ctrl->profile.support1 = a->profile.B1_Protocols;
706 ctrl->profile.support2 = a->profile.B2_Protocols;
707 ctrl->profile.support3 = a->profile.B3_Protocols;
708 /* manufacturer profile information */
709 ctrl->profile.manu[0] = a->man_profile.private_options;
710 ctrl->profile.manu[1] = a->man_profile.rtp_primary_payloads;
711 ctrl->profile.manu[2] = a->man_profile.rtp_additional_payloads;
712 ctrl->profile.manu[3] = 0;
713 ctrl->profile.manu[4] = 0;
714
715 capi_ctr_ready(ctrl);
716
717 DBG_TRC(("adapter added, max_adapter=%d", max_adapter));
718 return (1);
719}
720
721/*
722 * register appl
723 */
724static void diva_register_appl(struct capi_ctr *ctrl, __u16 appl,
725 capi_register_params * rp)
726{
727 APPL *this;
728 word bnum, xnum;
729 int i = 0;
730 unsigned char *p;
731 void *DataNCCI, *DataFlags, *ReceiveBuffer, *xbuffer_used;
732 void **xbuffer_ptr, **xbuffer_internal;
733 diva_os_spin_lock_magic_t old_irql;
734 unsigned int mem_len;
735 int nconn = rp->level3cnt;
736
737
738 if (diva_os_in_irq()) {
739 DBG_ERR(("CAPI_REGISTER - in irq context !"))
740 return;
741 }
742
743 DBG_TRC(("application register Id=%d", appl))
744
745 if (appl > MAX_APPL) {
746 DBG_ERR(("CAPI_REGISTER - appl.Id exceeds MAX_APPL"))
747 return;
748 }
749
750 if (nconn <= 0)
751 nconn = ctrl->profile.nbchannel * -nconn;
752
753 if (nconn == 0)
754 nconn = ctrl->profile.nbchannel;
755
756 DBG_LOG(("CAPI_REGISTER - Id = %d", appl))
757 DBG_LOG((" MaxLogicalConnections = %d(%d)", nconn, rp->level3cnt))
758 DBG_LOG((" MaxBDataBuffers = %d", rp->datablkcnt))
759 DBG_LOG((" MaxBDataLength = %d", rp->datablklen))
760
761 if (nconn < 1 ||
762 nconn > 255 ||
763 rp->datablklen < 80 ||
764 rp->datablklen > 2150 || rp->datablkcnt > 255) {
765 DBG_ERR(("CAPI_REGISTER - invalid parameters"))
766 return;
767 }
768
769 if (application[appl - 1].Id == appl) {
770 DBG_LOG(("CAPI_REGISTER - appl already registered"))
771 return; /* appl already registered */
772 }
773
774 /* alloc memory */
775
776 bnum = nconn * rp->datablkcnt;
777 xnum = nconn * MAX_DATA_B3;
778
779 mem_len = bnum * sizeof(word); /* DataNCCI */
780 mem_len += bnum * sizeof(word); /* DataFlags */
781 mem_len += bnum * rp->datablklen; /* ReceiveBuffer */
782 mem_len += xnum; /* xbuffer_used */
783 mem_len += xnum * sizeof(void *); /* xbuffer_ptr */
784 mem_len += xnum * sizeof(void *); /* xbuffer_internal */
785 mem_len += xnum * rp->datablklen; /* xbuffer_ptr[xnum] */
786
787 DBG_LOG((" Allocated Memory = %d", mem_len))
788 if (!(p = diva_os_malloc(0, mem_len))) {
789 DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
790 return;
791 }
792 memset(p, 0, mem_len);
793
794 DataNCCI = (void *)p;
795 p += bnum * sizeof(word);
796 DataFlags = (void *)p;
797 p += bnum * sizeof(word);
798 ReceiveBuffer = (void *)p;
799 p += bnum * rp->datablklen;
800 xbuffer_used = (void *)p;
801 p += xnum;
802 xbuffer_ptr = (void **)p;
803 p += xnum * sizeof(void *);
804 xbuffer_internal = (void **)p;
805 p += xnum * sizeof(void *);
806 for (i = 0; i < xnum; i++) {
807 xbuffer_ptr[i] = (void *)p;
808 p += rp->datablklen;
809 }
810
811 /* initialize application data */
812 diva_os_enter_spin_lock(&api_lock, &old_irql, "register_appl");
813
814 this = &application[appl - 1];
815 memset(this, 0, sizeof(APPL));
816
817 this->Id = appl;
818
819 for (i = 0; i < max_adapter; i++) {
820 adapter[i].CIP_Mask[appl - 1] = 0;
821 }
822
823 this->queue_size = 1000;
824
825 this->MaxNCCI = (byte) nconn;
826 this->MaxNCCIData = (byte) rp->datablkcnt;
827 this->MaxBuffer = bnum;
828 this->MaxDataLength = rp->datablklen;
829
830 this->DataNCCI = DataNCCI;
831 this->DataFlags = DataFlags;
832 this->ReceiveBuffer = ReceiveBuffer;
833 this->xbuffer_used = xbuffer_used;
834 this->xbuffer_ptr = xbuffer_ptr;
835 this->xbuffer_internal = xbuffer_internal;
836 for (i = 0; i < xnum; i++) {
837 this->xbuffer_ptr[i] = xbuffer_ptr[i];
838 }
839
840 CapiRegister(this->Id);
841 diva_os_leave_spin_lock(&api_lock, &old_irql, "register_appl");
842
843}
844
845/*
846 * release appl
847 */
848static void diva_release_appl(struct capi_ctr *ctrl, __u16 appl)
849{
850 diva_os_spin_lock_magic_t old_irql;
851 APPL *this = &application[appl - 1];
852 void *mem_to_free = NULL;
853
854 DBG_TRC(("application %d(%d) cleanup", this->Id, appl))
855
856 if (diva_os_in_irq()) {
857 DBG_ERR(("CAPI_RELEASE - in irq context !"))
858 return;
859 }
860
861 diva_os_enter_spin_lock(&api_lock, &old_irql, "release_appl");
862 if (this->Id) {
863 CapiRelease(this->Id);
864 mem_to_free = this->DataNCCI;
865 this->DataNCCI = NULL;
866 this->Id = 0;
867 }
868 diva_os_leave_spin_lock(&api_lock, &old_irql, "release_appl");
869
870 if (mem_to_free)
871 diva_os_free(0, mem_to_free);
872
873}
874
875/*
876 * send message
877 */
878static u16 diva_send_message(struct capi_ctr *ctrl,
879 diva_os_message_buffer_s * dmb)
880{
881 int i = 0;
882 word ret = 0;
883 diva_os_spin_lock_magic_t old_irql;
884 CAPI_MSG *msg = (CAPI_MSG *) DIVA_MESSAGE_BUFFER_DATA(dmb);
885 APPL *this = &application[GET_WORD(&msg->header.appl_id) - 1];
886 diva_card *card = ctrl->driverdata;
887 __u32 length = DIVA_MESSAGE_BUFFER_LEN(dmb);
888 word clength = GET_WORD(&msg->header.length);
889 word command = GET_WORD(&msg->header.command);
890 u16 retval = CAPI_NOERROR;
891
892 if (diva_os_in_irq()) {
893 DBG_ERR(("CAPI_SEND_MSG - in irq context !"))
894 return CAPI_REGOSRESOURCEERR;
895 }
896 DBG_PRV1(("Write - appl = %d, cmd = 0x%x", this->Id, command))
897
898 if (card->remove_in_progress) {
899 DBG_ERR(("CAPI_SEND_MSG - remove in progress!"))
900 return CAPI_REGOSRESOURCEERR;
901 }
902
903 diva_os_enter_spin_lock(&api_lock, &old_irql, "send message");
904
905 if (!this->Id) {
906 diva_os_leave_spin_lock(&api_lock, &old_irql, "send message");
907 return CAPI_ILLAPPNR;
908 }
909
910 /* patch controller number */
911 msg->header.controller = ControllerMap[card->Id]
912 | (msg->header.controller & 0x80); /* preserve external controller bit */
913
914 switch (command) {
915 default:
916 xlog("\x00\x02", msg, 0x80, clength);
917 break;
918
919 case _DATA_B3_I | RESPONSE:
920#ifndef DIVA_NO_DEBUGLIB
921 if (myDriverDebugHandle.dbgMask & DL_BLK)
922 xlog("\x00\x02", msg, 0x80, clength);
923#endif
924 break;
925
926 case _DATA_B3_R:
927#ifndef DIVA_NO_DEBUGLIB
928 if (myDriverDebugHandle.dbgMask & DL_BLK)
929 xlog("\x00\x02", msg, 0x80, clength);
930#endif
931
932 if (clength == 24)
933 clength = 22; /* workaround for PPcom bug */
934 /* header is always 22 */
935 if (GET_WORD(&msg->info.data_b3_req.Data_Length) >
936 this->MaxDataLength
937 || GET_WORD(&msg->info.data_b3_req.Data_Length) >
938 (length - clength)) {
939 DBG_ERR(("Write - invalid message size"))
940 retval = CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
941 goto write_end;
942 }
943
944 for (i = 0; i < (MAX_DATA_B3 * this->MaxNCCI)
945 && this->xbuffer_used[i]; i++);
946 if (i == (MAX_DATA_B3 * this->MaxNCCI)) {
947 DBG_ERR(("Write - too many data pending"))
948 retval = CAPI_SENDQUEUEFULL;
949 goto write_end;
950 }
951 msg->info.data_b3_req.Data = i;
952
953 this->xbuffer_internal[i] = NULL;
954 memcpy(this->xbuffer_ptr[i], &((__u8 *) msg)[clength],
955 GET_WORD(&msg->info.data_b3_req.Data_Length));
956
957#ifndef DIVA_NO_DEBUGLIB
958 if ((myDriverDebugHandle.dbgMask & DL_BLK)
959 && (myDriverDebugHandle.dbgMask & DL_XLOG)) {
960 int j;
961 for (j = 0; j <
962 GET_WORD(&msg->info.data_b3_req.Data_Length);
963 j += 256) {
964 DBG_BLK((((char *) this->xbuffer_ptr[i]) + j,
965 ((GET_WORD(&msg->info.data_b3_req.Data_Length) - j) <
966 256) ? (GET_WORD(&msg->info.data_b3_req.Data_Length) - j) : 256))
967 if (!(myDriverDebugHandle.dbgMask & DL_PRV0))
968 break; /* not more if not explicitely requested */
969 }
970 }
971#endif
972 break;
973 }
974
975 memcpy(mapped_msg, msg, (__u32) clength);
976 mapped_msg->header.controller = MapController(mapped_msg->header.controller);
977 mapped_msg->header.length = clength;
978 mapped_msg->header.command = command;
979 mapped_msg->header.number = GET_WORD(&msg->header.number);
980
981 ret = api_put(this, mapped_msg);
982 switch (ret) {
983 case 0:
984 break;
985 case _BAD_MSG:
986 DBG_ERR(("Write - bad message"))
987 retval = CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
988 break;
989 case _QUEUE_FULL:
990 DBG_ERR(("Write - queue full"))
991 retval = CAPI_SENDQUEUEFULL;
992 break;
993 default:
994 DBG_ERR(("Write - api_put returned unknown error"))
995 retval = CAPI_UNKNOWNNOTPAR;
996 break;
997 }
998
999 write_end:
1000 diva_os_leave_spin_lock(&api_lock, &old_irql, "send message");
1001 if (retval == CAPI_NOERROR)
1002 diva_os_free_message_buffer(dmb);
1003 return retval;
1004}
1005
1006
1007/*
1008 * cards request function
1009 */
1010static void DIRequest(ENTITY * e)
1011{
1012 DIVA_CAPI_ADAPTER *a = &(adapter[(byte) e->user[0]]);
1013 diva_card *os_card = (diva_card *) a->os_card;
1014
1015 if (e->Req && (a->FlowControlIdTable[e->ReqCh] == e->Id)) {
1016 a->FlowControlSkipTable[e->ReqCh] = 1;
1017 }
1018
1019 (*(os_card->d.request)) (e);
1020}
1021
1022/*
1023 * callback function from didd
1024 */
1025static void didd_callback(void *context, DESCRIPTOR * adapter, int removal)
1026{
1027 if (adapter->type == IDI_DADAPTER) {
1028 DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."));
1029 return;
1030 } else if (adapter->type == IDI_DIMAINT) {
1031 if (removal) {
1032 stop_dbg();
1033 } else {
1034 memcpy(&MAdapter, adapter, sizeof(MAdapter));
1035 dprintf = (DIVA_DI_PRINTF) MAdapter.request;
1036 DbgRegister("CAPI20", DRIVERRELEASE_CAPI, DBG_DEFAULT);
1037 }
1038 } else if ((adapter->type > 0) && (adapter->type < 16)) { /* IDI Adapter */
1039 if (removal) {
1040 divacapi_remove_card(adapter);
1041 } else {
1042 diva_add_card(adapter);
1043 }
1044 }
1045 return;
1046}
1047
1048/*
1049 * connect to didd
1050 */
1051static int divacapi_connect_didd(void)
1052{
1053 int x = 0;
1054 int dadapter = 0;
1055 IDI_SYNC_REQ req;
1056 DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
1057
1058 DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
1059
1060 for (x = 0; x < MAX_DESCRIPTORS; x++) {
1061 if (DIDD_Table[x].type == IDI_DIMAINT) { /* MAINT found */
1062 memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter));
1063 dprintf = (DIVA_DI_PRINTF) MAdapter.request;
1064 DbgRegister("CAPI20", DRIVERRELEASE_CAPI, DBG_DEFAULT);
1065 break;
1066 }
1067 }
1068 for (x = 0; x < MAX_DESCRIPTORS; x++) {
1069 if (DIDD_Table[x].type == IDI_DADAPTER) { /* DADAPTER found */
1070 dadapter = 1;
1071 memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
1072 req.didd_notify.e.Req = 0;
1073 req.didd_notify.e.Rc =
1074 IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
1075 req.didd_notify.info.callback = (void *)didd_callback;
1076 req.didd_notify.info.context = NULL;
1077 DAdapter.request((ENTITY *) & req);
1078 if (req.didd_notify.e.Rc != 0xff) {
1079 stop_dbg();
1080 return (0);
1081 }
1082 notify_handle = req.didd_notify.info.handle;
1083 }
1084 else if ((DIDD_Table[x].type > 0) && (DIDD_Table[x].type < 16)) { /* IDI Adapter found */
1085 diva_add_card(&DIDD_Table[x]);
1086 }
1087 }
1088
1089 if (!dadapter) {
1090 stop_dbg();
1091 }
1092
1093 return (dadapter);
1094}
1095
1096/*
1097 * diconnect from didd
1098 */
1099static void divacapi_disconnect_didd(void)
1100{
1101 IDI_SYNC_REQ req;
1102
1103 stop_dbg();
1104
1105 req.didd_notify.e.Req = 0;
1106 req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
1107 req.didd_notify.info.handle = notify_handle;
1108 DAdapter.request((ENTITY *) & req);
1109}
1110
1111/*
1112 * we do not provide date/time here,
1113 * the application should do this.
1114 */
1115int fax_head_line_time(char *buffer)
1116{
1117 return (0);
1118}
1119
1120/*
1121 * init (alloc) main structures
1122 */
1123static int DIVA_INIT_FUNCTION init_main_structs(void)
1124{
1125 if (!(mapped_msg = (CAPI_MSG *) diva_os_malloc(0, MAX_MSG_SIZE))) {
1126 DBG_ERR(("init: failed alloc mapped_msg."))
1127 return 0;
1128 }
1129
1130 if (!(adapter = diva_os_malloc(0, sizeof(DIVA_CAPI_ADAPTER) * MAX_DESCRIPTORS))) {
1131 DBG_ERR(("init: failed alloc adapter struct."))
1132 diva_os_free(0, mapped_msg);
1133 return 0;
1134 }
1135 memset(adapter, 0, sizeof(DIVA_CAPI_ADAPTER) * MAX_DESCRIPTORS);
1136
1137 if (!(application = diva_os_malloc(0, sizeof(APPL) * MAX_APPL))) {
1138 DBG_ERR(("init: failed alloc application struct."))
1139 diva_os_free(0, mapped_msg);
1140 diva_os_free(0, adapter);
1141 return 0;
1142 }
1143 memset(application, 0, sizeof(APPL) * MAX_APPL);
1144
1145 return (1);
1146}
1147
1148/*
1149 * remove (free) main structures
1150 */
1151static void remove_main_structs(void)
1152{
1153 if (application)
1154 diva_os_free(0, application);
1155 if (adapter)
1156 diva_os_free(0, adapter);
1157 if (mapped_msg)
1158 diva_os_free(0, mapped_msg);
1159}
1160
1161/*
1162 * api_remove_start
1163 */
1164static void do_api_remove_start(void)
1165{
1166 diva_os_spin_lock_magic_t old_irql;
1167 int ret = 1, count = 100;
1168
1169 do {
1170 diva_os_enter_spin_lock(&api_lock, &old_irql, "api remove start");
1171 ret = api_remove_start();
1172 diva_os_leave_spin_lock(&api_lock, &old_irql, "api remove start");
1173
1174 diva_os_sleep(10);
1175 } while (ret && count--);
1176
1177 if (ret)
1178 DBG_ERR(("could not remove signaling ID's"))
1179}
1180
1181/*
1182 * init
1183 */
1184int DIVA_INIT_FUNCTION init_capifunc(void)
1185{
1186 diva_os_initialize_spin_lock(&api_lock, "capifunc");
1187 memset(ControllerMap, 0, MAX_DESCRIPTORS + 1);
1188 max_adapter = 0;
1189
1190
1191 if (!init_main_structs()) {
1192 DBG_ERR(("init: failed to init main structs."))
1193 diva_os_destroy_spin_lock(&api_lock, "capifunc");
1194 return (0);
1195 }
1196
1197 if (!divacapi_connect_didd()) {
1198 DBG_ERR(("init: failed to connect to DIDD."))
1199 do_api_remove_start();
1200 divacapi_remove_cards();
1201 remove_main_structs();
1202 diva_os_destroy_spin_lock(&api_lock, "capifunc");
1203 return (0);
1204 }
1205
1206 return (1);
1207}
1208
1209/*
1210 * finit
1211 */
1212void DIVA_EXIT_FUNCTION finit_capifunc(void)
1213{
1214 do_api_remove_start();
1215 divacapi_disconnect_didd();
1216 divacapi_remove_cards();
1217 remove_main_structs();
1218 diva_os_destroy_spin_lock(&api_lock, "capifunc");
1219}
diff --git a/drivers/isdn/hardware/eicon/capifunc.h b/drivers/isdn/hardware/eicon/capifunc.h
new file mode 100644
index 000000000000..bd256f29738c
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/capifunc.h
@@ -0,0 +1,40 @@
1/* $Id: capifunc.h,v 1.11.4.1 2004/08/28 20:03:53 armin Exp $
2 *
3 * ISDN interface module for Eicon active cards DIVA.
4 * CAPI Interface common functions
5 *
6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 */
12
13#ifndef __CAPIFUNC_H__
14#define __CAPIFUNC_H__
15
16#define DRRELMAJOR 2
17#define DRRELMINOR 0
18#define DRRELEXTRA ""
19
20#define M_COMPANY "Eicon Networks"
21
22extern char DRIVERRELEASE_CAPI[];
23
24typedef struct _diva_card {
25 struct list_head list;
26 int remove_in_progress;
27 int Id;
28 struct capi_ctr capi_ctrl;
29 DIVA_CAPI_ADAPTER *adapter;
30 DESCRIPTOR d;
31 char name[32];
32} diva_card;
33
34/*
35 * prototypes
36 */
37int init_capifunc(void);
38void finit_capifunc(void);
39
40#endif /* __CAPIFUNC_H__ */
diff --git a/drivers/isdn/hardware/eicon/capimain.c b/drivers/isdn/hardware/eicon/capimain.c
new file mode 100644
index 000000000000..8fe4f3f09353
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/capimain.c
@@ -0,0 +1,147 @@
1/* $Id: capimain.c,v 1.24 2003/09/09 06:51:05 schindler Exp $
2 *
3 * ISDN interface module for Eicon active cards DIVA.
4 * CAPI Interface
5 *
6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 */
12
13#include <linux/config.h>
14#include <linux/module.h>
15#include <linux/init.h>
16#include <asm/uaccess.h>
17#include <linux/smp_lock.h>
18#include <linux/skbuff.h>
19
20#include "os_capi.h"
21
22#include "platform.h"
23#include "di_defs.h"
24#include "capi20.h"
25#include "divacapi.h"
26#include "cp_vers.h"
27#include "capifunc.h"
28
29static char *main_revision = "$Revision: 1.24 $";
30static char *DRIVERNAME =
31 "Eicon DIVA - CAPI Interface driver (http://www.melware.net)";
32static char *DRIVERLNAME = "divacapi";
33
34MODULE_DESCRIPTION("CAPI driver for Eicon DIVA cards");
35MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
36MODULE_SUPPORTED_DEVICE("CAPI and DIVA card drivers");
37MODULE_LICENSE("GPL");
38
39/*
40 * get revision number from revision string
41 */
42static char *getrev(const char *revision)
43{
44 char *rev;
45 char *p;
46 if ((p = strchr(revision, ':'))) {
47 rev = p + 2;
48 p = strchr(rev, '$');
49 *--p = 0;
50 } else
51 rev = "1.0";
52 return rev;
53
54}
55
56/*
57 * alloc a message buffer
58 */
59diva_os_message_buffer_s *diva_os_alloc_message_buffer(unsigned long size,
60 void **data_buf)
61{
62 diva_os_message_buffer_s *dmb = alloc_skb(size, GFP_ATOMIC);
63 if (dmb) {
64 *data_buf = skb_put(dmb, size);
65 }
66 return (dmb);
67}
68
69/*
70 * free a message buffer
71 */
72void diva_os_free_message_buffer(diva_os_message_buffer_s * dmb)
73{
74 kfree_skb(dmb);
75}
76
77/*
78 * proc function for controller info
79 */
80static int diva_ctl_read_proc(char *page, char **start, off_t off,
81 int count, int *eof, struct capi_ctr *ctrl)
82{
83 diva_card *card = (diva_card *) ctrl->driverdata;
84 int len = 0;
85
86 len += sprintf(page + len, "%s\n", ctrl->name);
87 len += sprintf(page + len, "Serial No. : %s\n", ctrl->serial);
88 len += sprintf(page + len, "Id : %d\n", card->Id);
89 len += sprintf(page + len, "Channels : %d\n", card->d.channels);
90
91 if (off + count >= len)
92 *eof = 1;
93 if (len < off)
94 return 0;
95 *start = page + off;
96 return ((count < len - off) ? count : len - off);
97}
98
99/*
100 * set additional os settings in capi_ctr struct
101 */
102void diva_os_set_controller_struct(struct capi_ctr *ctrl)
103{
104 ctrl->driver_name = DRIVERLNAME;
105 ctrl->load_firmware = NULL;
106 ctrl->reset_ctr = NULL;
107 ctrl->ctr_read_proc = diva_ctl_read_proc;
108 ctrl->owner = THIS_MODULE;
109}
110
111/*
112 * module init
113 */
114static int DIVA_INIT_FUNCTION divacapi_init(void)
115{
116 char tmprev[32];
117 int ret = 0;
118
119 sprintf(DRIVERRELEASE_CAPI, "%d.%d%s", DRRELMAJOR, DRRELMINOR,
120 DRRELEXTRA);
121
122 printk(KERN_INFO "%s\n", DRIVERNAME);
123 printk(KERN_INFO "%s: Rel:%s Rev:", DRIVERLNAME, DRIVERRELEASE_CAPI);
124 strcpy(tmprev, main_revision);
125 printk("%s Build: %s(%s)\n", getrev(tmprev),
126 diva_capi_common_code_build, DIVA_BUILD);
127
128 if (!(init_capifunc())) {
129 printk(KERN_ERR "%s: failed init capi_driver.\n",
130 DRIVERLNAME);
131 ret = -EIO;
132 }
133
134 return ret;
135}
136
137/*
138 * module exit
139 */
140static void DIVA_EXIT_FUNCTION divacapi_exit(void)
141{
142 finit_capifunc();
143 printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
144}
145
146module_init(divacapi_init);
147module_exit(divacapi_exit);
diff --git a/drivers/isdn/hardware/eicon/cardtype.h b/drivers/isdn/hardware/eicon/cardtype.h
new file mode 100644
index 000000000000..18a5c42fffdb
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/cardtype.h
@@ -0,0 +1,1098 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef _CARDTYPE_H_
27#define _CARDTYPE_H_
28#ifndef CARDTYPE_H_WANT_DATA
29#define CARDTYPE_H_WANT_DATA 0
30#endif
31#ifndef CARDTYPE_H_WANT_IDI_DATA
32#define CARDTYPE_H_WANT_IDI_DATA 0
33#endif
34#ifndef CARDTYPE_H_WANT_RESOURCE_DATA
35#define CARDTYPE_H_WANT_RESOURCE_DATA 1
36#endif
37#ifndef CARDTYPE_H_WANT_FILE_DATA
38#define CARDTYPE_H_WANT_FILE_DATA 1
39#endif
40/*
41 * D-channel protocol identifiers
42 *
43 * Attention: Unfortunately the identifiers defined here differ from
44 * the identifiers used in Protocol/1/Common/prot/q931.h .
45 * The only reason for this is that q931.h has not a global
46 * scope and we did not know about the definitions there.
47 * But the definitions here cannot be changed easily because
48 * they are used in setup scripts and programs.
49 * Thus the definitions here have to be mapped if they are
50 * used in the protocol code context !
51 *
52 * Now the identifiers are defined in the q931lib/constant.h file.
53 * Unfortunately this file has also not a global scope.
54 * But beginning with PROTTYPE_US any new identifier will get the same
55 * value as the corresponding PROT_* definition in q931lib/constant.h !
56 */
57#define PROTTYPE_MINVAL 0
58#define PROTTYPE_ETSI 0
59#define PROTTYPE_1TR6 1
60#define PROTTYPE_BELG 2
61#define PROTTYPE_FRANC 3
62#define PROTTYPE_ATEL 4
63#define PROTTYPE_NI 5 /* DMS 100, Nortel, National ISDN */
64#define PROTTYPE_5ESS 6 /* 5ESS , AT&T, 5ESS Custom */
65#define PROTTYPE_JAPAN 7
66#define PROTTYPE_SWED 8
67#define PROTTYPE_US 9 /* US autodetect */
68#define PROTTYPE_ITALY 10
69#define PROTTYPE_TWAN 11
70#define PROTTYPE_AUSTRAL 12
71#define PROTTYPE_4ESDN 13
72#define PROTTYPE_4ESDS 14
73#define PROTTYPE_4ELDS 15
74#define PROTTYPE_4EMGC 16
75#define PROTTYPE_4EMGI 17
76#define PROTTYPE_HONGKONG 18
77#define PROTTYPE_RBSCAS 19
78#define PROTTYPE_CORNETN 20
79#define PROTTYPE_QSIG 21
80#define PROTTYPE_NI_EWSD 22 /* EWSD, Siemens, National ISDN */
81#define PROTTYPE_5ESS_NI 23 /* 5ESS, Lucent, National ISDN */
82#define PROTTYPE_T1CORNETN 24
83#define PROTTYPE_CORNETNQ 25
84#define PROTTYPE_T1CORNETNQ 26
85#define PROTTYPE_T1QSIG 27
86#define PROTTYPE_E1UNCH 28
87#define PROTTYPE_T1UNCH 29
88#define PROTTYPE_E1CHAN 30
89#define PROTTYPE_T1CHAN 31
90#define PROTTYPE_R2CAS 32
91#define PROTTYPE_MAXVAL 32
92/*
93 * Card type identifiers
94 */
95#define CARD_UNKNOWN 0
96#define CARD_NONE 0
97 /* DIVA cards */
98#define CARDTYPE_DIVA_MCA 0
99#define CARDTYPE_DIVA_ISA 1
100#define CARDTYPE_DIVA_PCM 2
101#define CARDTYPE_DIVAPRO_ISA 3
102#define CARDTYPE_DIVAPRO_PCM 4
103#define CARDTYPE_DIVAPICO_ISA 5
104#define CARDTYPE_DIVAPICO_PCM 6
105 /* DIVA 2.0 cards */
106#define CARDTYPE_DIVAPRO20_PCI 7
107#define CARDTYPE_DIVA20_PCI 8
108 /* S cards */
109#define CARDTYPE_QUADRO_ISA 9
110#define CARDTYPE_S_ISA 10
111#define CARDTYPE_S_MCA 11
112#define CARDTYPE_SX_ISA 12
113#define CARDTYPE_SX_MCA 13
114#define CARDTYPE_SXN_ISA 14
115#define CARDTYPE_SXN_MCA 15
116#define CARDTYPE_SCOM_ISA 16
117#define CARDTYPE_SCOM_MCA 17
118#define CARDTYPE_PR_ISA 18
119#define CARDTYPE_PR_MCA 19
120 /* Diva Server cards (formerly called Maestra, later Amadeo) */
121#define CARDTYPE_MAESTRA_ISA 20
122#define CARDTYPE_MAESTRA_PCI 21
123 /* Diva Server cards to be developed (Quadro, Primary rate) */
124#define CARDTYPE_DIVASRV_Q_8M_PCI 22
125#define CARDTYPE_DIVASRV_P_30M_PCI 23
126#define CARDTYPE_DIVASRV_P_2M_PCI 24
127#define CARDTYPE_DIVASRV_P_9M_PCI 25
128 /* DIVA 2.0 cards */
129#define CARDTYPE_DIVA20_ISA 26
130#define CARDTYPE_DIVA20U_ISA 27
131#define CARDTYPE_DIVA20U_PCI 28
132#define CARDTYPE_DIVAPRO20_ISA 29
133#define CARDTYPE_DIVAPRO20U_ISA 30
134#define CARDTYPE_DIVAPRO20U_PCI 31
135 /* DIVA combi cards (piccola ISDN + rockwell V.34 modem) */
136#define CARDTYPE_DIVAMOBILE_PCM 32
137#define CARDTYPE_TDKGLOBALPRO_PCM 33
138 /* DIVA Pro PC OEM card for 'New Media Corporation' */
139#define CARDTYPE_NMC_DIVAPRO_PCM 34
140 /* DIVA Pro 2.0 OEM cards for 'British Telecom' */
141#define CARDTYPE_BT_EXLANE_PCI 35
142#define CARDTYPE_BT_EXLANE_ISA 36
143 /* DIVA low cost cards, 1st name DIVA 3.0, 2nd DIVA 2.01, 3rd ??? */
144#define CARDTYPE_DIVALOW_ISA 37
145#define CARDTYPE_DIVALOWU_ISA 38
146#define CARDTYPE_DIVALOW_PCI 39
147#define CARDTYPE_DIVALOWU_PCI 40
148 /* DIVA combi cards (piccola ISDN + rockwell V.90 modem) */
149#define CARDTYPE_DIVAMOBILE_V90_PCM 41
150#define CARDTYPE_TDKGLOBPRO_V90_PCM 42
151#define CARDTYPE_DIVASRV_P_23M_PCI 43
152#define CARDTYPE_DIVALOW_USB 44
153 /* DIVA Audio (CT) family */
154#define CARDTYPE_DIVA_CT_ST 45
155#define CARDTYPE_DIVA_CT_U 46
156#define CARDTYPE_DIVA_CTLITE_ST 47
157#define CARDTYPE_DIVA_CTLITE_U 48
158 /* DIVA ISDN plus V.90 series */
159#define CARDTYPE_DIVAISDN_V90_PCM 49
160#define CARDTYPE_DIVAISDN_V90_PCI 50
161#define CARDTYPE_DIVAISDN_TA 51
162 /* DIVA Server Voice cards */
163#define CARDTYPE_DIVASRV_VOICE_Q_8M_PCI 52
164 /* DIVA Server V2 cards */
165#define CARDTYPE_DIVASRV_Q_8M_V2_PCI 53
166#define CARDTYPE_DIVASRV_P_30M_V2_PCI 54
167 /* DIVA Server Voice V2 cards */
168#define CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI 55
169#define CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI 56
170 /* Diva LAN */
171#define CARDTYPE_DIVAISDN_LAN 57
172#define CARDTYPE_DIVA_202_PCI_ST 58
173#define CARDTYPE_DIVA_202_PCI_U 59
174#define CARDTYPE_DIVASRV_B_2M_V2_PCI 60
175#define CARDTYPE_DIVASRV_B_2F_PCI 61
176#define CARDTYPE_DIVALOW_USBV2 62
177#define CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI 63
178#define CARDTYPE_DIVA_PRO_30_PCI_ST 64
179#define CARDTYPE_DIVA_CT_ST_V20 65
180/* Diva Mobile V.90 PC Card and Diva ISDN PC Card */
181#define CARDTYPE_DIVAMOBILE_V2_PCM 66
182#define CARDTYPE_DIVA_V2_PCM 67
183/* Re-badged Diva Pro PC Card */
184#define CARDTYPE_DIVA_PC_CARD 68
185 /* next free card type identifier */
186#define CARDTYPE_MAX 69
187/*
188 * The card families
189 */
190#define FAMILY_DIVA 1
191#define FAMILY_S 2
192#define FAMILY_MAESTRA 3
193#define FAMILY_MAX 4
194/*
195 * The basic card types
196 */
197#define CARD_DIVA 1 /* DSP based, old DSP */
198#define CARD_PRO 2 /* DSP based, new DSP */
199#define CARD_PICO 3 /* HSCX based */
200#define CARD_S 4 /* IDI on board based */
201#define CARD_SX 5 /* IDI on board based */
202#define CARD_SXN 6 /* IDI on board based */
203#define CARD_SCOM 7 /* IDI on board based */
204#define CARD_QUAD 8 /* IDI on board based */
205#define CARD_PR 9 /* IDI on board based */
206#define CARD_MAE 10 /* IDI on board based */
207#define CARD_MAEQ 11 /* IDI on board based */
208#define CARD_MAEP 12 /* IDI on board based */
209#define CARD_DIVALOW 13 /* IPAC based */
210#define CARD_CT 14 /* SCOUT based */
211#define CARD_DIVATA 15 /* DIVA TA */
212#define CARD_DIVALAN 16 /* DIVA LAN */
213#define CARD_MAE2 17 /* IDI on board based */
214#define CARD_MAX 18
215/*
216 * The internal card types of the S family
217 */
218#define CARD_I_NONE 0
219#define CARD_I_S 0
220#define CARD_I_SX 1
221#define CARD_I_SCOM 2
222#define CARD_I_QUAD 3
223#define CARD_I_PR 4
224/*
225 * The bus types we support
226 */
227#define BUS_ISA 1
228#define BUS_PCM 2
229#define BUS_PCI 3
230#define BUS_MCA 4
231#define BUS_USB 5
232#define BUS_COM 6
233#define BUS_LAN 7
234/*
235 * The chips we use for B-channel traffic
236 */
237#define CHIP_NONE 0
238#define CHIP_DSP 1
239#define CHIP_HSCX 2
240#define CHIP_IPAC 3
241#define CHIP_SCOUT 4
242#define CHIP_EXTERN 5
243#define CHIP_IPACX 6
244/*
245 * The structures where the card properties are aggregated by id
246 */
247typedef struct CARD_PROPERTIES
248{ char *Name; /* official marketing name */
249 unsigned short PnPId; /* plug and play ID (for non PCMIA cards) */
250 unsigned short Version; /* major and minor version no of the card */
251 unsigned char DescType; /* card type to set in the IDI descriptor */
252 unsigned char Family; /* basic family of the card */
253 unsigned short Features; /* features bits to set in the IDI desc. */
254 unsigned char Card; /* basic card type */
255 unsigned char IType; /* internal type of S cards (read from ram) */
256 unsigned char Bus; /* bus type this card is designed for */
257 unsigned char Chip; /* chipset used on card */
258 unsigned char Adapters; /* number of adapters on card */
259 unsigned char Channels; /* # of channels per adapter */
260 unsigned short E_info; /* # of ram entity info structs per adapter */
261 unsigned short SizeIo; /* size of IO window per adapter */
262 unsigned short SizeMem; /* size of memory window per adapter */
263} CARD_PROPERTIES;
264typedef struct CARD_RESOURCE
265{ unsigned char Int [10];
266 unsigned short IoFirst;
267 unsigned short IoStep;
268 unsigned short IoCnt;
269 unsigned long MemFirst;
270 unsigned long MemStep;
271 unsigned short MemCnt;
272} CARD_RESOURCE;
273/* test if the card of type 't' is a plug & play card */
274#define IS_PNP(t) \
275( \
276 ( \
277 CardProperties[t].Bus != BUS_ISA \
278 && \
279 CardProperties[t].Bus != BUS_MCA \
280 ) \
281 || \
282 ( \
283 CardProperties[t].Family != FAMILY_S \
284 && \
285 CardProperties[t].Card != CARD_DIVA \
286 ) \
287)
288/* extract IDI Descriptor info for card type 't' (p == DescType/Features) */
289#define IDI_PROP(t,p) (CardProperties[t].p)
290#if CARDTYPE_H_WANT_DATA
291#if CARDTYPE_H_WANT_IDI_DATA
292/* include "di_defs.h" for IDI adapter type and feature flag definitions */
293#include "di_defs.h"
294#else /*!CARDTYPE_H_WANT_IDI_DATA*/
295/* define IDI adapter types and feature flags here to prevent inclusion */
296#ifndef IDI_ADAPTER_S
297#define IDI_ADAPTER_S 1
298#define IDI_ADAPTER_PR 2
299#define IDI_ADAPTER_DIVA 3
300#define IDI_ADAPTER_MAESTRA 4
301#endif
302#ifndef DI_VOICE
303#define DI_VOICE 0x0 /* obsolete define */
304#define DI_FAX3 0x1
305#define DI_MODEM 0x2
306#define DI_POST 0x4
307#define DI_V110 0x8
308#define DI_V120 0x10
309#define DI_POTS 0x20
310#define DI_CODEC 0x40
311#define DI_MANAGE 0x80
312#define DI_V_42 0x0100
313#define DI_EXTD_FAX 0x0200 /* Extended FAX (ECM, 2D, T.6, Polling) */
314#define DI_AT_PARSER 0x0400 /* Build-in AT Parser in the L2 */
315#define DI_VOICE_OVER_IP 0x0800 /* Voice over IP support */
316#endif
317#endif /*CARDTYPE_H_WANT_IDI_DATA*/
318#define DI_V1x0 (DI_V110 | DI_V120)
319#define DI_NULL 0x0000
320#if defined(SOFT_DSP_SUPPORT)
321#define SOFT_DSP_ADD_FEATURES (DI_MODEM | DI_FAX3 | DI_AT_PARSER)
322#else
323#define SOFT_DSP_ADD_FEATURES 0
324#endif
325#if defined(SOFT_V110_SUPPORT)
326#define DI_SOFT_V110 DI_V110
327#else
328#define DI_SOFT_V110 0
329#endif
330/*--- CardProperties [Index=CARDTYPE_....] ---------------------------------*/
331CARD_PROPERTIES CardProperties [ ] =
332{
333{ /* 0 */
334 "Diva MCA", 0x6336, 0x0100,
335 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V1x0 | DI_FAX3,
336 CARD_DIVA, CARD_I_NONE, BUS_MCA, CHIP_DSP,
337 1, 2, 0, 8, 0
338},
339{ /* 1 */
340 "Diva ISA", 0x0000, 0x0100,
341 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V1x0 | DI_FAX3,
342 CARD_DIVA, CARD_I_NONE, BUS_ISA, CHIP_DSP,
343 1, 2, 0, 8, 0
344},
345{ /* 2 */
346 "Diva/PCM", 0x0000, 0x0100,
347 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V1x0 | DI_FAX3,
348 CARD_DIVA, CARD_I_NONE, BUS_PCM, CHIP_DSP,
349 1, 2, 0, 8, 0
350},
351{ /* 3 */
352 "Diva PRO ISA", 0x0031, 0x0100,
353 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_CODEC,
354 CARD_PRO, CARD_I_NONE, BUS_ISA, CHIP_DSP,
355 1, 2, 0, 8, 0
356},
357{ /* 4 */
358 "Diva PRO PC-Card", 0x0000, 0x0100,
359 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM,
360 CARD_PRO, CARD_I_NONE, BUS_PCM, CHIP_DSP,
361 1, 2, 0, 8, 0
362},
363{ /* 5 */
364 "Diva PICCOLA ISA", 0x0051, 0x0100,
365 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
366 CARD_PICO, CARD_I_NONE, BUS_ISA, CHIP_HSCX,
367 1, 2, 0, 8, 0
368},
369{ /* 6 */
370 "Diva PICCOLA PCM", 0x0000, 0x0100,
371 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
372 CARD_PICO, CARD_I_NONE, BUS_PCM, CHIP_HSCX,
373 1, 2, 0, 8, 0
374},
375{ /* 7 */
376 "Diva PRO 2.0 S/T PCI", 0xe001, 0x0200,
377 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_POTS,
378 CARD_PRO, CARD_I_NONE, BUS_PCI, CHIP_DSP,
379 1, 2, 0, 8, 0
380},
381{ /* 8 */
382 "Diva 2.0 S/T PCI", 0xe002, 0x0200,
383 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | DI_POTS | SOFT_DSP_ADD_FEATURES,
384 CARD_PICO, CARD_I_NONE, BUS_PCI, CHIP_HSCX,
385 1, 2, 0, 8, 0
386},
387{ /* 9 */
388 "QUADRO ISA", 0x0000, 0x0100,
389 IDI_ADAPTER_S, FAMILY_S, DI_NULL,
390 CARD_QUAD, CARD_I_QUAD, BUS_ISA, CHIP_NONE,
391 4, 2, 16, 0, 0x800
392},
393{ /* 10 */
394 "S ISA", 0x0000, 0x0100,
395 IDI_ADAPTER_S, FAMILY_S, DI_CODEC,
396 CARD_S, CARD_I_S, BUS_ISA, CHIP_NONE,
397 1, 1, 16, 0, 0x800
398},
399{ /* 11 */
400 "S MCA", 0x6a93, 0x0100,
401 IDI_ADAPTER_S, FAMILY_S, DI_CODEC,
402 CARD_S, CARD_I_S, BUS_MCA, CHIP_NONE,
403 1, 1, 16, 16, 0x400
404},
405{ /* 12 */
406 "SX ISA", 0x0000, 0x0100,
407 IDI_ADAPTER_S, FAMILY_S, DI_NULL,
408 CARD_SX, CARD_I_SX, BUS_ISA, CHIP_NONE,
409 1, 2, 16, 0, 0x800
410},
411{ /* 13 */
412 "SX MCA", 0x6a93, 0x0100,
413 IDI_ADAPTER_S, FAMILY_S, DI_NULL,
414 CARD_SX, CARD_I_SX, BUS_MCA, CHIP_NONE,
415 1, 2, 16, 16, 0x400
416},
417{ /* 14 */
418 "SXN ISA", 0x0000, 0x0100,
419 IDI_ADAPTER_S, FAMILY_S, DI_NULL,
420 CARD_SXN, CARD_I_SCOM, BUS_ISA, CHIP_NONE,
421 1, 2, 16, 0, 0x800
422},
423{ /* 15 */
424 "SXN MCA", 0x6a93, 0x0100,
425 IDI_ADAPTER_S, FAMILY_S, DI_NULL,
426 CARD_SXN, CARD_I_SCOM, BUS_MCA, CHIP_NONE,
427 1, 2, 16, 16, 0x400
428},
429{ /* 16 */
430 "SCOM ISA", 0x0000, 0x0100,
431 IDI_ADAPTER_S, FAMILY_S, DI_CODEC,
432 CARD_SCOM, CARD_I_SCOM, BUS_ISA, CHIP_NONE,
433 1, 2, 16, 0, 0x800
434},
435{ /* 17 */
436 "SCOM MCA", 0x6a93, 0x0100,
437 IDI_ADAPTER_S, FAMILY_S, DI_CODEC,
438 CARD_SCOM, CARD_I_SCOM, BUS_MCA, CHIP_NONE,
439 1, 2, 16, 16, 0x400
440},
441{ /* 18 */
442 "S2M ISA", 0x0000, 0x0100,
443 IDI_ADAPTER_PR, FAMILY_S, DI_NULL,
444 CARD_PR, CARD_I_PR, BUS_ISA, CHIP_NONE,
445 1, 30, 256, 0, 0x4000
446},
447{ /* 19 */
448 "S2M MCA", 0x6abb, 0x0100,
449 IDI_ADAPTER_PR, FAMILY_S, DI_NULL,
450 CARD_PR, CARD_I_PR, BUS_MCA, CHIP_NONE,
451 1, 30, 256, 16, 0x4000
452},
453{ /* 20 */
454 "Diva Server BRI-2M ISA", 0x0041, 0x0100,
455 IDI_ADAPTER_MAESTRA,FAMILY_MAESTRA, DI_V1x0 | DI_FAX3 | DI_MODEM,
456 CARD_MAE, CARD_I_NONE, BUS_ISA, CHIP_DSP,
457 1, 2, 16, 8, 0
458},
459{ /* 21 */
460 "Diva Server BRI-2M PCI", 0xE010, 0x0100,
461 IDI_ADAPTER_MAESTRA,FAMILY_MAESTRA, DI_V1x0 | DI_FAX3 | DI_MODEM,
462 CARD_MAE, CARD_I_NONE, BUS_PCI, CHIP_DSP,
463 1, 2, 16, 8, 0
464},
465{ /* 22 */
466 "Diva Server 4BRI-8M PCI", 0xE012, 0x0100,
467 IDI_ADAPTER_MAESTRA,FAMILY_MAESTRA, DI_V1x0 | DI_FAX3 | DI_MODEM,
468 CARD_MAEQ, CARD_I_NONE, BUS_PCI, CHIP_DSP,
469 4, 2, 16, 8, 0
470},
471{ /* 23 */
472 "Diva Server PRI-30M PCI", 0xE014, 0x0100,
473 IDI_ADAPTER_MAESTRA,FAMILY_MAESTRA, DI_V1x0 | DI_FAX3 | DI_MODEM,
474 CARD_MAEP, CARD_I_NONE, BUS_PCI, CHIP_DSP,
475 1, 30, 256, 8, 0
476},
477{ /* 24 */
478 "Diva Server PRI-2M PCI", 0xe014, 0x0100,
479 IDI_ADAPTER_MAESTRA,FAMILY_MAESTRA, DI_V1x0 | DI_FAX3 | DI_MODEM,
480 CARD_MAEP, CARD_I_NONE, BUS_PCI, CHIP_DSP,
481 1, 30, 256, 8, 0
482},
483{ /* 25 */
484 "Diva Server PRI-9M PCI", 0x0000, 0x0100,
485 IDI_ADAPTER_MAESTRA,FAMILY_MAESTRA, DI_V1x0 | DI_FAX3 | DI_MODEM,
486 CARD_MAEP, CARD_I_NONE, BUS_PCI, CHIP_DSP,
487 1, 30, 256, 8, 0
488},
489{ /* 26 */
490 "Diva 2.0 S/T ISA", 0x0071, 0x0200,
491 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | DI_POTS | SOFT_DSP_ADD_FEATURES,
492 CARD_PICO, CARD_I_NONE, BUS_ISA, CHIP_HSCX,
493 1, 2, 0, 8, 0
494},
495{ /* 27 */
496 "Diva 2.0 U ISA", 0x0091, 0x0200,
497 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | DI_POTS | SOFT_DSP_ADD_FEATURES,
498 CARD_PICO, CARD_I_NONE, BUS_ISA, CHIP_HSCX,
499 1, 2, 0, 8, 0
500},
501{ /* 28 */
502 "Diva 2.0 U PCI", 0xe004, 0x0200,
503 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | DI_POTS | SOFT_DSP_ADD_FEATURES,
504 CARD_PICO, CARD_I_NONE, BUS_PCI, CHIP_HSCX,
505 1, 2, 0, 8, 0
506},
507{ /* 29 */
508 "Diva PRO 2.0 S/T ISA", 0x0061, 0x0200,
509 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_POTS,
510 CARD_PRO, CARD_I_NONE, BUS_ISA, CHIP_DSP,
511 1, 2, 0, 8, 0
512},
513{ /* 30 */
514 "Diva PRO 2.0 U ISA", 0x0081, 0x0200,
515 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_POTS,
516 CARD_PRO, CARD_I_NONE, BUS_ISA, CHIP_DSP,
517 1, 2, 0, 8, 0
518},
519{ /* 31 */
520 "Diva PRO 2.0 U PCI", 0xe003, 0x0200,
521 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_POTS,
522 CARD_PRO, CARD_I_NONE, BUS_PCI, CHIP_DSP,
523 1, 2, 0, 8, 0
524},
525{ /* 32 */
526 "Diva MOBILE", 0x0000, 0x0100,
527 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
528 CARD_PICO, CARD_I_NONE, BUS_PCM, CHIP_HSCX,
529 1, 2, 0, 8, 0
530},
531{ /* 33 */
532 "TDK DFI3600", 0x0000, 0x0100,
533 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
534 CARD_PICO, CARD_I_NONE, BUS_PCM, CHIP_HSCX,
535 1, 2, 0, 8, 0
536},
537{ /* 34 (OEM version of 4 - "Diva PRO PC-Card") */
538 "New Media ISDN", 0x0000, 0x0100,
539 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM,
540 CARD_PRO, CARD_I_NONE, BUS_PCM, CHIP_DSP,
541 1, 2, 0, 8, 0
542},
543{ /* 35 (OEM version of 7 - "Diva PRO 2.0 S/T PCI") */
544 "BT ExLane PCI", 0xe101, 0x0200,
545 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_POTS,
546 CARD_PRO, CARD_I_NONE, BUS_PCI, CHIP_DSP,
547 1, 2, 0, 8, 0
548},
549{ /* 36 (OEM version of 29 - "Diva PRO 2.0 S/T ISA") */
550 "BT ExLane ISA", 0x1061, 0x0200,
551 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_POTS,
552 CARD_PRO, CARD_I_NONE, BUS_ISA, CHIP_DSP,
553 1, 2, 0, 8, 0
554},
555{ /* 37 */
556 "Diva 2.01 S/T ISA", 0x00A1, 0x0300,
557 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
558 CARD_DIVALOW, CARD_I_NONE, BUS_ISA, CHIP_IPAC,
559 1, 2, 0, 8, 0
560},
561{ /* 38 */
562 "Diva 2.01 U ISA", 0x00B1, 0x0300,
563 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
564 CARD_DIVALOW, CARD_I_NONE, BUS_ISA, CHIP_IPAC,
565 1, 2, 0, 8, 0
566},
567{ /* 39 */
568 "Diva 2.01 S/T PCI", 0xe005, 0x0300,
569 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
570 CARD_DIVALOW, CARD_I_NONE, BUS_PCI, CHIP_IPAC,
571 1, 2, 0, 8, 0
572},
573{ /* 40 no ID yet */
574 "Diva 2.01 U PCI", 0x0000, 0x0300,
575 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
576 CARD_DIVALOW, CARD_I_NONE, BUS_PCI, CHIP_IPAC,
577 1, 2, 0, 8, 0
578},
579{ /* 41 */
580 "Diva MOBILE V.90", 0x0000, 0x0100,
581 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
582 CARD_PICO, CARD_I_NONE, BUS_PCM, CHIP_HSCX,
583 1, 2, 0, 8, 0
584},
585{ /* 42 */
586 "TDK DFI3600 V.90", 0x0000, 0x0100,
587 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
588 CARD_PICO, CARD_I_NONE, BUS_PCM, CHIP_HSCX,
589 1, 2, 0, 8, 0
590},
591{ /* 43 */
592 "Diva Server PRI-23M PCI", 0xe014, 0x0100,
593 IDI_ADAPTER_MAESTRA,FAMILY_MAESTRA, DI_V1x0 | DI_FAX3 | DI_MODEM,
594 CARD_MAEP, CARD_I_NONE, BUS_PCI, CHIP_DSP,
595 1, 30, 256, 8, 0
596},
597{ /* 44 */
598 "Diva 2.01 S/T USB", 0x1000, 0x0300,
599 IDI_ADAPTER_DIVA ,FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
600 CARD_DIVALOW, CARD_I_NONE, BUS_USB, CHIP_IPAC,
601 1, 2, 0, 8, 0
602},
603{ /* 45 */
604 "Diva CT S/T PCI", 0xe006, 0x0300,
605 IDI_ADAPTER_DIVA ,FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_CODEC,
606 CARD_CT, CARD_I_NONE, BUS_PCI, CHIP_DSP,
607 1, 2, 0, 0, 0
608},
609{ /* 46 */
610 "Diva CT U PCI", 0xe007, 0x0300,
611 IDI_ADAPTER_DIVA ,FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_CODEC,
612 CARD_CT, CARD_I_NONE, BUS_PCI, CHIP_DSP,
613 1, 2, 0, 0, 0
614},
615{ /* 47 */
616 "Diva CT Lite S/T PCI", 0xe008, 0x0300,
617 IDI_ADAPTER_DIVA ,FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_CODEC,
618 CARD_CT, CARD_I_NONE, BUS_PCI, CHIP_DSP,
619 1, 2, 0, 0, 0
620},
621{ /* 48 */
622 "Diva CT Lite U PCI", 0xe009, 0x0300,
623 IDI_ADAPTER_DIVA ,FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_CODEC,
624 CARD_CT, CARD_I_NONE, BUS_PCI, CHIP_DSP,
625 1, 2, 0, 0, 0
626},
627{ /* 49 */
628 "Diva ISDN+V.90 PC Card", 0x8D8C, 0x0100,
629 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_CODEC,
630 CARD_DIVALOW, CARD_I_NONE, BUS_PCM, CHIP_IPAC,
631 1, 2, 0, 8, 0
632},
633{ /* 50 */
634 "Diva ISDN+V.90 PCI", 0xe00A, 0x0100,
635 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
636 CARD_DIVALOW, CARD_I_NONE, BUS_PCI, CHIP_IPAC,
637 1, 2, 0, 8, 0
638},
639{ /* 51 (DivaTA) no ID */
640 "Diva TA", 0x0000, 0x0300,
641 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V110 | DI_FAX3 | SOFT_DSP_ADD_FEATURES,
642 CARD_DIVATA, CARD_I_NONE, BUS_COM, CHIP_EXTERN,
643 1, 1, 0, 8, 0
644},
645{ /* 52 (Diva Server 4BRI-8M PCI adapter enabled for Voice) */
646 "Diva Server Voice 4BRI-8M PCI", 0xE016, 0x0100,
647 IDI_ADAPTER_MAESTRA,FAMILY_MAESTRA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_VOICE_OVER_IP,
648 CARD_MAEQ, CARD_I_NONE, BUS_PCI, CHIP_DSP,
649 4, 2, 16, 8, 0
650},
651{ /* 53 (Diva Server 4BRI 2.0 adapter) */
652 "Diva Server 4BRI-8M 2.0 PCI", 0xE013, 0x0200,
653 IDI_ADAPTER_MAESTRA,FAMILY_MAESTRA, DI_V1x0 | DI_FAX3 | DI_MODEM,
654 CARD_MAEQ, CARD_I_NONE, BUS_PCI, CHIP_DSP,
655 4, 2, 16, 8, 0
656},
657{ /* 54 (Diva Server PRI 2.0 adapter) */
658 "Diva Server PRI 2.0 PCI", 0xE015, 0x0200,
659 IDI_ADAPTER_MAESTRA,FAMILY_MAESTRA, DI_V1x0 | DI_FAX3 | DI_MODEM,
660 CARD_MAEP, CARD_I_NONE, BUS_PCI, CHIP_DSP,
661 1, 30, 256, 8, 0
662},
663{ /* 55 (Diva Server 4BRI-8M 2.0 PCI adapter enabled for Voice) */
664 "Diva Server Voice 4BRI-8M 2.0 PCI", 0xE017, 0x0200,
665 IDI_ADAPTER_MAESTRA,FAMILY_MAESTRA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_VOICE_OVER_IP,
666 CARD_MAEQ, CARD_I_NONE, BUS_PCI, CHIP_DSP,
667 4, 2, 16, 8, 0
668},
669{ /* 56 (Diva Server PRI 2.0 PCI adapter enabled for Voice) */
670 "Diva Server Voice PRI 2.0 PCI", 0xE019, 0x0200,
671 IDI_ADAPTER_MAESTRA,FAMILY_MAESTRA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_VOICE_OVER_IP,
672 CARD_MAEP, CARD_I_NONE, BUS_PCI, CHIP_DSP,
673 1, 30, 256, 8, 0
674},
675{
676 /* 57 (DivaLan ) no ID */
677 "Diva LAN", 0x0000, 0x0300,
678 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V110 | DI_FAX3 | SOFT_DSP_ADD_FEATURES,
679 CARD_DIVALAN, CARD_I_NONE, BUS_LAN, CHIP_EXTERN,
680 1, 1, 0, 8, 0
681},
682{ /* 58 */
683 "Diva 2.02 PCI S/T", 0xE00B, 0x0300,
684 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES | DI_SOFT_V110,
685 CARD_DIVALOW, CARD_I_NONE, BUS_PCI, CHIP_IPACX,
686 1, 2, 0, 8, 0
687},
688{ /* 59 */
689 "Diva 2.02 PCI U", 0xE00C, 0x0300,
690 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
691 CARD_DIVALOW, CARD_I_NONE, BUS_PCI, CHIP_IPACX,
692 1, 2, 0, 8, 0
693},
694{ /* 60 */
695 "Diva Server BRI-2M 2.0 PCI", 0xE018, 0x0200,
696 IDI_ADAPTER_MAESTRA,FAMILY_MAESTRA, DI_V1x0 | DI_FAX3 | DI_MODEM,
697 CARD_MAE2, CARD_I_NONE, BUS_PCI, CHIP_DSP,
698 1, 2, 16, 8, 0
699},
700{ /* 61 (the previous name was Diva Server BRI-2F 2.0 PCI) */
701 "Diva Server 2FX", 0xE01A, 0x0200,
702 IDI_ADAPTER_MAESTRA,FAMILY_MAESTRA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_SOFT_V110,
703 CARD_MAE2, CARD_I_NONE, BUS_PCI, CHIP_IPACX,
704 1, 2, 16, 8, 0
705},
706{ /* 62 */
707 " Diva ISDN USB 2.0", 0x1003, 0x0300,
708 IDI_ADAPTER_DIVA ,FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
709 CARD_DIVALOW, CARD_I_NONE, BUS_USB, CHIP_IPACX,
710 1, 2, 0, 8, 0
711},
712{ /* 63 (Diva Server BRI-2M 2.0 PCI adapter enabled for Voice) */
713 "Diva Server Voice BRI-2M 2.0 PCI", 0xE01B, 0x0200,
714 IDI_ADAPTER_MAESTRA,FAMILY_MAESTRA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_VOICE_OVER_IP,
715 CARD_MAE2, CARD_I_NONE, BUS_PCI, CHIP_DSP,
716 1, 2, 16, 8, 0
717},
718{ /* 64 */
719 "Diva Pro 3.0 PCI", 0xe00d, 0x0300,
720 IDI_ADAPTER_DIVA ,FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM,
721 CARD_PRO, CARD_I_NONE, BUS_PCI, CHIP_DSP,
722 1, 2, 0, 0, 0
723},
724{ /* 65 */
725 "Diva ISDN + CT 2.0", 0xE00E, 0x0300,
726 IDI_ADAPTER_DIVA ,FAMILY_DIVA, DI_V1x0 | DI_FAX3 | DI_MODEM | DI_CODEC,
727 CARD_CT, CARD_I_NONE, BUS_PCI, CHIP_DSP,
728 1, 2, 0, 0, 0
729},
730{ /* 66 */
731 "Diva Mobile V.90 PC Card", 0x8331, 0x0100,
732 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
733 CARD_PICO, CARD_I_NONE, BUS_PCM, CHIP_IPACX,
734 1, 2, 0, 8, 0
735},
736{ /* 67 */
737 "Diva ISDN PC Card", 0x8311, 0x0100,
738 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
739 CARD_PICO, CARD_I_NONE, BUS_PCM, CHIP_IPACX,
740 1, 2, 0, 8, 0
741},
742{ /* 68 */
743 "Diva ISDN PC Card", 0x0000, 0x0100,
744 IDI_ADAPTER_DIVA, FAMILY_DIVA, DI_V120 | SOFT_DSP_ADD_FEATURES,
745 CARD_PRO, CARD_I_NONE, BUS_PCM, CHIP_DSP,
746 1, 2, 0, 8, 0
747},
748} ;
749#if CARDTYPE_H_WANT_RESOURCE_DATA
750/*--- CardResource [Index=CARDTYPE_....] ---------------------------(GEI)-*/
751CARD_RESOURCE CardResource [ ] = {
752/* Interrupts IO-Address Mem-Address */
753/* 0*/ { 3,4,9,0,0,0,0,0,0,0, 0x200,0x20,16, 0x0,0x0,0 }, // DIVA MCA
754/* 1*/ { 3,4,9,10,11,12,0,0,0,0, 0x200,0x20,16, 0x0,0x0,0 }, // DIVA ISA
755/* 2*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // DIVA PCMCIA
756/* 3*/ { 3,5,7,9,10,11,12,14,15,0, 0x200,0x20,16, 0x0,0x0,0 }, // DIVA PRO ISA
757/* 4*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // DIVA PRO PCMCIA
758/* 5*/ { 3,5,7,9,10,11,12,14,15,0, 0x200,0x20,16, 0x0,0x0,0 }, // DIVA PICCOLA ISA
759/* 6*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // DIVA PICCOLA PCMCIA
760/* 7*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // DIVA PRO 2.0 PCI
761/* 8*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // DIVA 2.0 PCI
762/* 9*/ { 3,4,5,7,9,10,11,12,0,0, 0x0,0x0,0, 0x80000,0x2000,64 }, // QUADRO ISA
763/*10*/ { 3,4,9,10,11,12,0,0,0,0, 0x0,0x0,0, 0xc0000,0x2000,16 }, // S ISA
764/*11*/ { 3,4,9,0,0,0,0,0,0,0, 0xc00,0x10,16, 0xc0000,0x2000,16 }, // S MCA
765/*12*/ { 3,4,9,10,11,12,0,0,0,0, 0x0,0x0,0, 0xc0000,0x2000,16 }, // SX ISA
766/*13*/ { 3,4,9,0,0,0,0,0,0,0, 0xc00,0x10,16, 0xc0000,0x2000,16 }, // SX MCA
767/*14*/ { 3,4,5,7,9,10,11,12,0,0, 0x0,0x0,0, 0x80000,0x0800,256 }, // SXN ISA
768/*15*/ { 3,4,9,0,0,0,0,0,0,0, 0xc00,0x10,16, 0xc0000,0x2000,16 }, // SXN MCA
769/*16*/ { 3,4,5,7,9,10,11,12,0,0, 0x0,0x0,0, 0x80000,0x0800,256 }, // SCOM ISA
770/*17*/ { 3,4,9,0,0,0,0,0,0,0, 0xc00,0x10,16, 0xc0000,0x2000,16 }, // SCOM MCA
771/*18*/ { 3,4,5,7,9,10,11,12,0,0, 0x0,0x0,0, 0xc0000,0x4000,16 }, // S2M ISA
772/*19*/ { 3,4,9,0,0,0,0,0,0,0, 0xc00,0x10,16, 0xc0000,0x4000,16 }, // S2M MCA
773/*20*/ { 3,5,7,9,10,11,12,14,15,0, 0x200,0x20,16, 0x0,0x0,0 }, // MAESTRA ISA
774/*21*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // MAESTRA PCI
775/*22*/ { 3,5,7,9,10,11,12,14,15,0, 0x200,0x20,16, 0x0,0x0,0 }, // MAESTRA QUADRO ISA
776/*23*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x20,2048, 0x0,0x0,0 }, // MAESTRA QUADRO PCI
777/*24*/ { 3,5,7,9,10,11,12,14,15,0, 0x200,0x20,16, 0x0,0x0,0 }, // MAESTRA PRIMARY ISA
778/*25*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // MAESTRA PRIMARY PCI
779/*26*/ { 3,5,7,9,10,11,12,14,15,0, 0x200,0x20,16, 0x0,0x0,0 }, // DIVA 2.0 ISA
780/*27*/ { 3,5,7,9,10,11,12,14,15,0, 0x200,0x20,16, 0x0,0x0,0 }, // DIVA 2.0 /U ISA
781/*28*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // DIVA 2.0 /U PCI
782/*29*/ { 3,5,7,9,10,11,12,14,15,0, 0x200,0x20,16, 0x0,0x0,0 }, // DIVA PRO 2.0 ISA
783/*30*/ { 3,5,7,9,10,11,12,14,15,0, 0x200,0x20,16, 0x0,0x0,0 }, // DIVA PRO 2.0 /U ISA
784/*31*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // DIVA PRO 2.0 /U PCI
785/*32*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // DIVA MOBILE
786/*33*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // TDK DFI3600 (same as DIVA MOBILE [32])
787/*34*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // New Media ISDN (same as DIVA PRO PCMCIA [4])
788/*35*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // BT ExLane PCI (same as DIVA PRO 2.0 PCI [7])
789/*36*/ { 3,5,7,9,10,11,12,14,15,0, 0x200,0x20,16, 0x0,0x0,0 }, // BT ExLane ISA (same as DIVA PRO 2.0 ISA [29])
790/*37*/ { 3,5,7,9,10,11,12,14,15,0, 0x200,0x20,16, 0x0,0x0,0 }, // DIVA 2.01 S/T ISA
791/*38*/ { 3,5,7,9,10,11,12,14,15,0, 0x200,0x20,16, 0x0,0x0,0 }, // DIVA 2.01 U ISA
792/*39*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // DIVA 2.01 S/T PCI
793/*40*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // DIVA 2.01 U PCI
794/*41*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // DIVA MOBILE V.90
795/*42*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // TDK DFI3600 V.90 (same as DIVA MOBILE V.90 [39])
796/*43*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x20,2048, 0x0,0x0,0 }, // DIVA Server PRI-23M PCI
797/*44*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // DIVA 2.01 S/T USB
798/*45*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // DIVA CT S/T PCI
799/*46*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // DIVA CT U PCI
800/*47*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // DIVA CT Lite S/T PCI
801/*48*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // DIVA CT Lite U PCI
802/*49*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // DIVA ISDN+V.90 PC Card
803/*50*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // DIVA ISDN+V.90 PCI
804/*51*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // DIVA TA
805/*52*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x20,2048, 0x0,0x0,0 }, // MAESTRA VOICE QUADRO PCI
806/*53*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x20,2048, 0x0,0x0,0 }, // MAESTRA VOICE QUADRO PCI
807/*54*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // MAESTRA VOICE PRIMARY PCI
808/*55*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x20,2048, 0x0,0x0,0 }, // MAESTRA VOICE QUADRO PCI
809/*56*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // MAESTRA VOICE PRIMARY PCI
810/*57*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // DIVA LAN
811/*58*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // DIVA 2.02 S/T PCI
812/*59*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // DIVA 2.02 U PCI
813/*60*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // Diva Server BRI-2M 2.0 PCI
814/*61*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // Diva Server BRI-2F PCI
815/*62*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // DIVA 2.01 S/T USB
816/*63*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // Diva Server Voice BRI-2M 2.0 PCI
817/*64*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // DIVA 3.0 PCI
818/*65*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // DIVA CT S/T PCI V2.0
819/*66*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // DIVA Mobile V.90 PC Card
820/*67*/ { 0,0,0,0,0,0,0,0,0,0, 0x0,0x0,0, 0x0,0x0,0 }, // DIVA ISDN PC Card
821/*68*/ { 3,4,5,7,9,10,11,12,14,15, 0x0,0x8,8192, 0x0,0x0,0 }, // DIVA ISDN PC Card
822};
823#endif /*CARDTYPE_H_WANT_RESOURCE_DATA*/
824#else /*!CARDTYPE_H_WANT_DATA*/
825extern CARD_PROPERTIES CardProperties [] ;
826extern CARD_RESOURCE CardResource [] ;
827#endif /*CARDTYPE_H_WANT_DATA*/
828/*
829 * all existing download files
830 */
831#define CARD_DSP_CNT 5
832#define CARD_PROT_CNT 9
833#define CARD_FT_UNKNOWN 0
834#define CARD_FT_B 1
835#define CARD_FT_D 2
836#define CARD_FT_S 3
837#define CARD_FT_M 4
838#define CARD_FT_NEW_DSP_COMBIFILE 5 /* File format of new DSP code (the DSP code powered by Telindus) */
839#define CARD_FILE_NONE 0
840#define CARD_B_S 1
841#define CARD_B_P 2
842#define CARD_D_K1 3
843#define CARD_D_K2 4
844#define CARD_D_H 5
845#define CARD_D_V 6
846#define CARD_D_M 7
847#define CARD_D_F 8
848#define CARD_P_S_E 9
849#define CARD_P_S_1 10
850#define CARD_P_S_B 11
851#define CARD_P_S_F 12
852#define CARD_P_S_A 13
853#define CARD_P_S_N 14
854#define CARD_P_S_5 15
855#define CARD_P_S_J 16
856#define CARD_P_SX_E 17
857#define CARD_P_SX_1 18
858#define CARD_P_SX_B 19
859#define CARD_P_SX_F 20
860#define CARD_P_SX_A 21
861#define CARD_P_SX_N 22
862#define CARD_P_SX_5 23
863#define CARD_P_SX_J 24
864#define CARD_P_SY_E 25
865#define CARD_P_SY_1 26
866#define CARD_P_SY_B 27
867#define CARD_P_SY_F 28
868#define CARD_P_SY_A 29
869#define CARD_P_SY_N 30
870#define CARD_P_SY_5 31
871#define CARD_P_SY_J 32
872#define CARD_P_SQ_E 33
873#define CARD_P_SQ_1 34
874#define CARD_P_SQ_B 35
875#define CARD_P_SQ_F 36
876#define CARD_P_SQ_A 37
877#define CARD_P_SQ_N 38
878#define CARD_P_SQ_5 39
879#define CARD_P_SQ_J 40
880#define CARD_P_P_E 41
881#define CARD_P_P_1 42
882#define CARD_P_P_B 43
883#define CARD_P_P_F 44
884#define CARD_P_P_A 45
885#define CARD_P_P_N 46
886#define CARD_P_P_5 47
887#define CARD_P_P_J 48
888#define CARD_P_M_E 49
889#define CARD_P_M_1 50
890#define CARD_P_M_B 51
891#define CARD_P_M_F 52
892#define CARD_P_M_A 53
893#define CARD_P_M_N 54
894#define CARD_P_M_5 55
895#define CARD_P_M_J 56
896#define CARD_P_S_S 57
897#define CARD_P_SX_S 58
898#define CARD_P_SY_S 59
899#define CARD_P_SQ_S 60
900#define CARD_P_P_S 61
901#define CARD_P_M_S 62
902#define CARD_D_NEW_DSP_COMBIFILE 63
903typedef struct CARD_FILES_DATA
904{
905 char * Name;
906 unsigned char Type;
907}
908CARD_FILES_DATA;
909typedef struct CARD_FILES
910{
911 unsigned char Boot;
912 unsigned char Dsp [CARD_DSP_CNT];
913 unsigned char DspTelindus;
914 unsigned char Prot [CARD_PROT_CNT];
915}
916CARD_FILES;
917#if CARDTYPE_H_WANT_DATA
918#if CARDTYPE_H_WANT_FILE_DATA
919CARD_FILES_DATA CardFData [] = {
920// Filename Filetype
921 0, CARD_FT_UNKNOWN,
922 "didnload.bin", CARD_FT_B,
923 "diprload.bin", CARD_FT_B,
924 "didiva.bin", CARD_FT_D,
925 "didivapp.bin", CARD_FT_D,
926 "dihscx.bin", CARD_FT_D,
927 "div110.bin", CARD_FT_D,
928 "dimodem.bin", CARD_FT_D,
929 "difax.bin", CARD_FT_D,
930 "di_etsi.bin", CARD_FT_S,
931 "di_1tr6.bin", CARD_FT_S,
932 "di_belg.bin", CARD_FT_S,
933 "di_franc.bin", CARD_FT_S,
934 "di_atel.bin", CARD_FT_S,
935 "di_ni.bin", CARD_FT_S,
936 "di_5ess.bin", CARD_FT_S,
937 "di_japan.bin", CARD_FT_S,
938 "di_etsi.sx", CARD_FT_S,
939 "di_1tr6.sx", CARD_FT_S,
940 "di_belg.sx", CARD_FT_S,
941 "di_franc.sx", CARD_FT_S,
942 "di_atel.sx", CARD_FT_S,
943 "di_ni.sx", CARD_FT_S,
944 "di_5ess.sx", CARD_FT_S,
945 "di_japan.sx", CARD_FT_S,
946 "di_etsi.sy", CARD_FT_S,
947 "di_1tr6.sy", CARD_FT_S,
948 "di_belg.sy", CARD_FT_S,
949 "di_franc.sy", CARD_FT_S,
950 "di_atel.sy", CARD_FT_S,
951 "di_ni.sy", CARD_FT_S,
952 "di_5ess.sy", CARD_FT_S,
953 "di_japan.sy", CARD_FT_S,
954 "di_etsi.sq", CARD_FT_S,
955 "di_1tr6.sq", CARD_FT_S,
956 "di_belg.sq", CARD_FT_S,
957 "di_franc.sq", CARD_FT_S,
958 "di_atel.sq", CARD_FT_S,
959 "di_ni.sq", CARD_FT_S,
960 "di_5ess.sq", CARD_FT_S,
961 "di_japan.sq", CARD_FT_S,
962 "di_etsi.p", CARD_FT_S,
963 "di_1tr6.p", CARD_FT_S,
964 "di_belg.p", CARD_FT_S,
965 "di_franc.p", CARD_FT_S,
966 "di_atel.p", CARD_FT_S,
967 "di_ni.p", CARD_FT_S,
968 "di_5ess.p", CARD_FT_S,
969 "di_japan.p", CARD_FT_S,
970 "di_etsi.sm", CARD_FT_M,
971 "di_1tr6.sm", CARD_FT_M,
972 "di_belg.sm", CARD_FT_M,
973 "di_franc.sm", CARD_FT_M,
974 "di_atel.sm", CARD_FT_M,
975 "di_ni.sm", CARD_FT_M,
976 "di_5ess.sm", CARD_FT_M,
977 "di_japan.sm", CARD_FT_M,
978 "di_swed.bin", CARD_FT_S,
979 "di_swed.sx", CARD_FT_S,
980 "di_swed.sy", CARD_FT_S,
981 "di_swed.sq", CARD_FT_S,
982 "di_swed.p", CARD_FT_S,
983 "di_swed.sm", CARD_FT_M,
984 "didspdld.bin", CARD_FT_NEW_DSP_COMBIFILE
985};
986CARD_FILES CardFiles [] =
987{
988 { /* CARD_UNKNOWN */
989 CARD_FILE_NONE,
990 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
991 CARD_FILE_NONE,
992 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
993 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
994 CARD_FILE_NONE
995 },
996 { /* CARD_DIVA */
997 CARD_FILE_NONE,
998 CARD_D_K1, CARD_D_H, CARD_D_V, CARD_FILE_NONE, CARD_D_F,
999 CARD_D_NEW_DSP_COMBIFILE,
1000 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1001 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1002 CARD_FILE_NONE
1003 },
1004 { /* CARD_PRO */
1005 CARD_FILE_NONE,
1006 CARD_D_K2, CARD_D_H, CARD_D_V, CARD_D_M, CARD_D_F,
1007 CARD_D_NEW_DSP_COMBIFILE,
1008 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1009 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1010 CARD_FILE_NONE
1011 },
1012 { /* CARD_PICO */
1013 CARD_FILE_NONE,
1014 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1015 CARD_FILE_NONE,
1016 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1017 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1018 CARD_FILE_NONE
1019 },
1020 { /* CARD_S */
1021 CARD_B_S,
1022 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1023 CARD_FILE_NONE,
1024 CARD_P_S_E, CARD_P_S_1, CARD_P_S_B, CARD_P_S_F,
1025 CARD_P_S_A, CARD_P_S_N, CARD_P_S_5, CARD_P_S_J,
1026 CARD_P_S_S
1027 },
1028 { /* CARD_SX */
1029 CARD_B_S,
1030 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1031 CARD_FILE_NONE,
1032 CARD_P_SX_E, CARD_P_SX_1, CARD_P_SX_B, CARD_P_SX_F,
1033 CARD_P_SX_A, CARD_P_SX_N, CARD_P_SX_5, CARD_P_SX_J,
1034 CARD_P_SX_S
1035 },
1036 { /* CARD_SXN */
1037 CARD_B_S,
1038 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1039 CARD_FILE_NONE,
1040 CARD_P_SY_E, CARD_P_SY_1, CARD_P_SY_B, CARD_P_SY_F,
1041 CARD_P_SY_A, CARD_P_SY_N, CARD_P_SY_5, CARD_P_SY_J,
1042 CARD_P_SY_S
1043 },
1044 { /* CARD_SCOM */
1045 CARD_B_S,
1046 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1047 CARD_FILE_NONE,
1048 CARD_P_SY_E, CARD_P_SY_1, CARD_P_SY_B, CARD_P_SY_F,
1049 CARD_P_SY_A, CARD_P_SY_N, CARD_P_SY_5, CARD_P_SY_J,
1050 CARD_P_SY_S
1051 },
1052 { /* CARD_QUAD */
1053 CARD_B_S,
1054 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1055 CARD_FILE_NONE,
1056 CARD_P_SQ_E, CARD_P_SQ_1, CARD_P_SQ_B, CARD_P_SQ_F,
1057 CARD_P_SQ_A, CARD_P_SQ_N, CARD_P_SQ_5, CARD_P_SQ_J,
1058 CARD_P_SQ_S
1059 },
1060 { /* CARD_PR */
1061 CARD_B_P,
1062 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1063 CARD_FILE_NONE,
1064 CARD_P_P_E, CARD_P_P_1, CARD_P_P_B, CARD_P_P_F,
1065 CARD_P_P_A, CARD_P_P_N, CARD_P_P_5, CARD_P_P_J,
1066 CARD_P_P_S
1067 },
1068 { /* CARD_MAE */
1069 CARD_FILE_NONE,
1070 CARD_D_K2, CARD_D_H, CARD_D_V, CARD_D_M, CARD_D_F,
1071 CARD_D_NEW_DSP_COMBIFILE,
1072 CARD_P_M_E, CARD_P_M_1, CARD_P_M_B, CARD_P_M_F,
1073 CARD_P_M_A, CARD_P_M_N, CARD_P_M_5, CARD_P_M_J,
1074 CARD_P_M_S
1075 },
1076 { /* CARD_MAEQ */ /* currently not supported */
1077 CARD_FILE_NONE,
1078 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1079 CARD_FILE_NONE,
1080 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1081 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1082 CARD_FILE_NONE
1083 },
1084 { /* CARD_MAEP */ /* currently not supported */
1085 CARD_FILE_NONE,
1086 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1087 CARD_FILE_NONE,
1088 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1089 CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE, CARD_FILE_NONE,
1090 CARD_FILE_NONE
1091 }
1092};
1093#endif /*CARDTYPE_H_WANT_FILE_DATA*/
1094#else /*!CARDTYPE_H_WANT_DATA*/
1095extern CARD_FILES_DATA CardFData [] ;
1096extern CARD_FILES CardFiles [] ;
1097#endif /*CARDTYPE_H_WANT_DATA*/
1098#endif /* _CARDTYPE_H_ */
diff --git a/drivers/isdn/hardware/eicon/cp_vers.h b/drivers/isdn/hardware/eicon/cp_vers.h
new file mode 100644
index 000000000000..cb5ada31111c
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/cp_vers.h
@@ -0,0 +1,26 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26static char diva_capi_common_code_build[] = "102-28";
diff --git a/drivers/isdn/hardware/eicon/dadapter.c b/drivers/isdn/hardware/eicon/dadapter.c
new file mode 100644
index 000000000000..6e548a222ef1
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/dadapter.c
@@ -0,0 +1,366 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#include "platform.h"
27#include "pc.h"
28#include "debuglib.h"
29#include "di_defs.h"
30#include "divasync.h"
31#include "dadapter.h"
32/* --------------------------------------------------------------------------
33 Adapter array change notification framework
34 -------------------------------------------------------------------------- */
35typedef struct _didd_adapter_change_notification {
36 didd_adapter_change_callback_t callback;
37 void IDI_CALL_ENTITY_T * context;
38} didd_adapter_change_notification_t, \
39 * IDI_CALL_ENTITY_T pdidd_adapter_change_notification_t;
40#define DIVA_DIDD_MAX_NOTIFICATIONS 256
41static didd_adapter_change_notification_t\
42 NotificationTable[DIVA_DIDD_MAX_NOTIFICATIONS];
43/* --------------------------------------------------------------------------
44 Array to held adapter information
45 -------------------------------------------------------------------------- */
46static DESCRIPTOR HandleTable[NEW_MAX_DESCRIPTORS];
47dword Adapters = 0; /* Number of adapters */
48/* --------------------------------------------------------------------------
49 Shadow IDI_DIMAINT
50 and 'shadow' debug stuff
51 -------------------------------------------------------------------------- */
52static void no_printf (unsigned char * format, ...)
53{
54#ifdef EBUG
55 va_list ap;
56 va_start (ap, format);
57 debug((format, ap));
58 va_end (ap);
59#endif
60}
61
62/* -------------------------------------------------------------------------
63 Portable debug Library
64 ------------------------------------------------------------------------- */
65#include "debuglib.c"
66
67static DESCRIPTOR MAdapter = {IDI_DIMAINT, /* Adapter Type */
68 0x00, /* Channels */
69 0x0000, /* Features */
70 (IDI_CALL)no_printf};
71/* --------------------------------------------------------------------------
72 DAdapter. Only IDI clients with buffer, that is huge enough to
73 get all descriptors will receive information about DAdapter
74 { byte type, byte channels, word features, IDI_CALL request }
75 -------------------------------------------------------------------------- */
76static void IDI_CALL_LINK_T diva_dadapter_request (ENTITY IDI_CALL_ENTITY_T *);
77static DESCRIPTOR DAdapter = {IDI_DADAPTER, /* Adapter Type */
78 0x00, /* Channels */
79 0x0000, /* Features */
80 diva_dadapter_request };
81/* --------------------------------------------------------------------------
82 LOCALS
83 -------------------------------------------------------------------------- */
84static dword diva_register_adapter_callback (\
85 didd_adapter_change_callback_t callback,
86 void IDI_CALL_ENTITY_T* context);
87static void diva_remove_adapter_callback (dword handle);
88static void diva_notify_adapter_change (DESCRIPTOR* d, int removal);
89static diva_os_spin_lock_t didd_spin;
90/* --------------------------------------------------------------------------
91 Should be called as first step, after driver init
92 -------------------------------------------------------------------------- */
93void diva_didd_load_time_init (void) {
94 memset (&HandleTable[0], 0x00, sizeof(HandleTable));
95 memset (&NotificationTable[0], 0x00, sizeof(NotificationTable));
96 diva_os_initialize_spin_lock (&didd_spin, "didd");
97}
98/* --------------------------------------------------------------------------
99 Should be called as last step, if driver does unload
100 -------------------------------------------------------------------------- */
101void diva_didd_load_time_finit (void) {
102 diva_os_destroy_spin_lock (&didd_spin, "didd");
103}
104/* --------------------------------------------------------------------------
105 Called in order to register new adapter in adapter array
106 return adapter handle (> 0) on success
107 return -1 adapter array overflow
108 -------------------------------------------------------------------------- */
109static int diva_didd_add_descriptor (DESCRIPTOR* d) {
110 diva_os_spin_lock_magic_t irql;
111 int i;
112 if (d->type == IDI_DIMAINT) {
113 if (d->request) {
114 MAdapter.request = d->request;
115 dprintf = (DIVA_DI_PRINTF)d->request;
116 diva_notify_adapter_change (&MAdapter, 0); /* Inserted */
117 DBG_TRC (("DIMAINT registered, dprintf=%08x", d->request))
118 } else {
119 DBG_TRC (("DIMAINT removed"))
120 diva_notify_adapter_change (&MAdapter, 1); /* About to remove */
121 MAdapter.request = (IDI_CALL)no_printf;
122 dprintf = no_printf;
123 }
124 return (NEW_MAX_DESCRIPTORS);
125 }
126 for (i = 0; i < NEW_MAX_DESCRIPTORS; i++) {
127 diva_os_enter_spin_lock (&didd_spin, &irql, "didd_add");
128 if (HandleTable[i].type == 0) {
129 memcpy (&HandleTable[i], d, sizeof(*d));
130 Adapters++;
131 diva_os_leave_spin_lock (&didd_spin, &irql, "didd_add");
132 diva_notify_adapter_change (d, 0); /* we have new adapter */
133 DBG_TRC (("Add adapter[%d], request=%08x", (i+1), d->request))
134 return (i+1);
135 }
136 diva_os_leave_spin_lock (&didd_spin, &irql, "didd_add");
137 }
138 DBG_ERR (("Can't add adapter, out of resources"))
139 return (-1);
140}
141/* --------------------------------------------------------------------------
142 Called in order to remove one registered adapter from array
143 return adapter handle (> 0) on success
144 return 0 on success
145 -------------------------------------------------------------------------- */
146static int diva_didd_remove_descriptor (IDI_CALL request) {
147 diva_os_spin_lock_magic_t irql;
148 int i;
149 if (request == MAdapter.request) {
150 DBG_TRC(("DIMAINT removed"))
151 dprintf = no_printf;
152 diva_notify_adapter_change (&MAdapter, 1); /* About to remove */
153 MAdapter.request = (IDI_CALL)no_printf;
154 return (0);
155 }
156 for (i = 0; (Adapters && (i < NEW_MAX_DESCRIPTORS)); i++) {
157 if (HandleTable[i].request == request) {
158 diva_notify_adapter_change (&HandleTable[i], 1); /* About to remove */
159 diva_os_enter_spin_lock (&didd_spin, &irql, "didd_rm");
160 memset (&HandleTable[i], 0x00, sizeof(HandleTable[0]));
161 Adapters--;
162 diva_os_leave_spin_lock (&didd_spin, &irql, "didd_rm");
163 DBG_TRC (("Remove adapter[%d], request=%08x", (i+1), request))
164 return (0);
165 }
166 }
167 DBG_ERR (("Invalid request=%08x, can't remove adapter", request))
168 return (-1);
169}
170/* --------------------------------------------------------------------------
171 Read adapter array
172 return 1 if not enough space to save all available adapters
173 -------------------------------------------------------------------------- */
174static int diva_didd_read_adapter_array (DESCRIPTOR* buffer, int length) {
175 diva_os_spin_lock_magic_t irql;
176 int src, dst;
177 memset (buffer, 0x00, length);
178 length /= sizeof(DESCRIPTOR);
179 DBG_TRC (("DIDD_Read, space = %d, Adapters = %d", length, Adapters+2))
180
181 diva_os_enter_spin_lock (&didd_spin, &irql, "didd_read");
182 for (src = 0, dst = 0;
183 (Adapters && (src < NEW_MAX_DESCRIPTORS) && (dst < length));
184 src++) {
185 if (HandleTable[src].type) {
186 memcpy (&buffer[dst], &HandleTable[src], sizeof(DESCRIPTOR));
187 dst++;
188 }
189 }
190 diva_os_leave_spin_lock (&didd_spin, &irql, "didd_read");
191 if (dst < length) {
192 memcpy (&buffer[dst], &MAdapter, sizeof(DESCRIPTOR));
193 dst++;
194 } else {
195 DBG_ERR (("Can't write DIMAINT. Array too small"))
196 }
197 if (dst < length) {
198 memcpy (&buffer[dst], &DAdapter, sizeof(DESCRIPTOR));
199 dst++;
200 } else {
201 DBG_ERR (("Can't write DADAPTER. Array too small"))
202 }
203 DBG_TRC (("Read %d adapters", dst))
204 return (dst == length);
205}
206/* --------------------------------------------------------------------------
207 DAdapter request function.
208 This function does process only synchronous requests, and is used
209 for reception/registration of new interfaces
210 -------------------------------------------------------------------------- */
211static void IDI_CALL_LINK_T diva_dadapter_request (\
212 ENTITY IDI_CALL_ENTITY_T *e) {
213 IDI_SYNC_REQ *syncReq = (IDI_SYNC_REQ *)e ;
214 if (e->Req) { /* We do not process it, also return error */
215 e->Rc = OUT_OF_RESOURCES;
216 DBG_ERR (("Can't process async request, Req=%02x", e->Req))
217 return;
218 }
219 /*
220 So, we process sync request
221 */
222 switch (e->Rc) {
223 case IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY: {
224 diva_didd_adapter_notify_t* pinfo = &syncReq->didd_notify.info;
225 pinfo->handle = diva_register_adapter_callback (\
226 (didd_adapter_change_callback_t)pinfo->callback,
227 (void IDI_CALL_ENTITY_T *)pinfo->context);
228 e->Rc = 0xff;
229 } break;
230 case IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY: {
231 diva_didd_adapter_notify_t* pinfo = &syncReq->didd_notify.info;
232 diva_remove_adapter_callback (pinfo->handle);
233 e->Rc = 0xff;
234 } break;
235 case IDI_SYNC_REQ_DIDD_ADD_ADAPTER: {
236 diva_didd_add_adapter_t* pinfo = &syncReq->didd_add_adapter.info;
237 if (diva_didd_add_descriptor ((DESCRIPTOR*)pinfo->descriptor) < 0) {
238 e->Rc = OUT_OF_RESOURCES;
239 } else {
240 e->Rc = 0xff;
241 }
242 } break;
243 case IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER: {
244 diva_didd_remove_adapter_t* pinfo = &syncReq->didd_remove_adapter.info;
245 if (diva_didd_remove_descriptor ((IDI_CALL)pinfo->p_request) < 0) {
246 e->Rc = OUT_OF_RESOURCES;
247 } else {
248 e->Rc = 0xff;
249 }
250 } break;
251 case IDI_SYNC_REQ_DIDD_READ_ADAPTER_ARRAY: {
252 diva_didd_read_adapter_array_t* pinfo =\
253 &syncReq->didd_read_adapter_array.info;
254 if (diva_didd_read_adapter_array ((DESCRIPTOR*)pinfo->buffer,
255 (int)pinfo->length)) {
256 e->Rc = OUT_OF_RESOURCES;
257 } else {
258 e->Rc = 0xff;
259 }
260 } break;
261 default:
262 DBG_ERR (("Can't process sync request, Req=%02x", e->Rc))
263 e->Rc = OUT_OF_RESOURCES;
264 }
265}
266/* --------------------------------------------------------------------------
267 IDI client does register his notification function
268 -------------------------------------------------------------------------- */
269static dword diva_register_adapter_callback (\
270 didd_adapter_change_callback_t callback,
271 void IDI_CALL_ENTITY_T* context) {
272 diva_os_spin_lock_magic_t irql;
273 dword i;
274
275 for (i = 0; i < DIVA_DIDD_MAX_NOTIFICATIONS; i++) {
276 diva_os_enter_spin_lock (&didd_spin, &irql, "didd_nfy_add");
277 if (!NotificationTable[i].callback) {
278 NotificationTable[i].callback = callback;
279 NotificationTable[i].context = context;
280 diva_os_leave_spin_lock (&didd_spin, &irql, "didd_nfy_add");
281 DBG_TRC(("Register adapter notification[%d]=%08x", i+1, callback))
282 return (i+1);
283 }
284 diva_os_leave_spin_lock (&didd_spin, &irql, "didd_nfy_add");
285 }
286 DBG_ERR (("Can't register adapter notification, overflow"))
287 return (0);
288}
289/* --------------------------------------------------------------------------
290 IDI client does register his notification function
291 -------------------------------------------------------------------------- */
292static void diva_remove_adapter_callback (dword handle) {
293 diva_os_spin_lock_magic_t irql;
294 if (handle && ((--handle) < DIVA_DIDD_MAX_NOTIFICATIONS)) {
295 diva_os_enter_spin_lock (&didd_spin, &irql, "didd_nfy_rm");
296 NotificationTable[handle].callback = NULL;
297 NotificationTable[handle].context = NULL;
298 diva_os_leave_spin_lock (&didd_spin, &irql, "didd_nfy_rm");
299 DBG_TRC(("Remove adapter notification[%d]", (int)(handle+1)))
300 return;
301 }
302 DBG_ERR(("Can't remove adapter notification, handle=%d", handle))
303}
304/* --------------------------------------------------------------------------
305 Notify all client about adapter array change
306 Does suppose following behavior in the client side:
307 Step 1: Redister Notification
308 Step 2: Read Adapter Array
309 -------------------------------------------------------------------------- */
310static void diva_notify_adapter_change (DESCRIPTOR* d, int removal) {
311 int i, do_notify;
312 didd_adapter_change_notification_t nfy;
313 diva_os_spin_lock_magic_t irql;
314 for (i = 0; i < DIVA_DIDD_MAX_NOTIFICATIONS; i++) {
315 do_notify = 0;
316 diva_os_enter_spin_lock (&didd_spin, &irql, "didd_nfy");
317 if (NotificationTable[i].callback) {
318 memcpy (&nfy, &NotificationTable[i], sizeof(nfy));
319 do_notify = 1;
320 }
321 diva_os_leave_spin_lock (&didd_spin, &irql, "didd_nfy");
322 if (do_notify) {
323 (*(nfy.callback))(nfy.context, d, removal);
324 }
325 }
326}
327/* --------------------------------------------------------------------------
328 For all systems, that are linked by Kernel Mode Linker this is ONLY one
329 function thet should be exported by this device driver
330 IDI clients should look for IDI_DADAPTER, and use request function
331 of this adapter (sync request) in order to receive appropriate services:
332 - add new adapter
333 - remove existing adapter
334 - add adapter array notification
335 - remove adapter array notification
336 (read adapter is redundant in this case)
337 INPUT:
338 buffer - pointer to buffer that will receive adapter array
339 length - length (in bytes) of space in buffer
340 OUTPUT:
341 Adapter array will be written to memory described by 'buffer'
342 If the last adapter seen in the returned adapter array is
343 IDI_DADAPTER or if last adapter in array does have type '0', then
344 it was enougth space in buffer to accommodate all available
345 adapter descriptors
346 *NOTE 1 (debug interface):
347 The IDI adapter of type 'IDI_DIMAINT' does register as 'request'
348 famous 'dprintf' function (of type DI_PRINTF, please look
349 include/debuglib.c and include/debuglib.h) for details.
350 So dprintf is not exported from module debug module directly,
351 instead of this IDI_DIMAINT is registered.
352 Module load order will receive in this case:
353 1. DIDD (this file)
354 2. DIMAINT does load and register 'IDI_DIMAINT', at this step
355 DIDD should be able to get 'dprintf', save it, and
356 register with DIDD by means of 'dprintf' function.
357 3. any other driver is loaded and is able to access adapter array
358 and debug interface
359 This approach does allow to load/unload debug interface on demand,
360 and save memory, it it is necessary.
361 -------------------------------------------------------------------------- */
362void IDI_CALL_LINK_T DIVA_DIDD_Read (void IDI_CALL_ENTITY_T * buffer,
363 int length) {
364 diva_didd_read_adapter_array (buffer, length);
365}
366
diff --git a/drivers/isdn/hardware/eicon/dadapter.h b/drivers/isdn/hardware/eicon/dadapter.h
new file mode 100644
index 000000000000..3575ac912e6c
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/dadapter.h
@@ -0,0 +1,34 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef __DIVA_DIDD_DADAPTER_INC__
27#define __DIVA_DIDD_DADAPTER_INC__
28
29void diva_didd_load_time_init (void);
30void diva_didd_load_time_finit (void);
31
32#define NEW_MAX_DESCRIPTORS 64
33
34#endif
diff --git a/drivers/isdn/hardware/eicon/dbgioctl.h b/drivers/isdn/hardware/eicon/dbgioctl.h
new file mode 100644
index 000000000000..0fb6f5e88b60
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/dbgioctl.h
@@ -0,0 +1,198 @@
1
2/*
3 *
4 Copyright (c) Eicon Technology Corporation, 2000.
5 *
6 This source file is supplied for the use with Eicon
7 Technology Corporation's range of DIVA Server Adapters.
8 *
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13 *
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
16 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU General Public License for more details.
18 *
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24/*------------------------------------------------------------------*/
25/* file: dbgioctl.h */
26/*------------------------------------------------------------------*/
27
28#if !defined(__DBGIOCTL_H__)
29
30#define __DBGIOCTL_H__
31
32#ifdef NOT_YET_NEEDED
33/*
34 * The requested operation is passed in arg0 of DbgIoctlArgs,
35 * additional arguments (if any) in arg1, arg2 and arg3.
36 */
37
38typedef struct
39{ ULONG arg0 ;
40 ULONG arg1 ;
41 ULONG arg2 ;
42 ULONG arg3 ;
43} DbgIoctlArgs ;
44
45#define DBG_COPY_LOGS 0 /* copy debugs to user until buffer full */
46 /* arg1: size threshold */
47 /* arg2: timeout in milliseconds */
48
49#define DBG_FLUSH_LOGS 1 /* flush pending debugs to user buffer */
50 /* arg1: internal driver id */
51
52#define DBG_LIST_DRVS 2 /* return the list of registered drivers */
53
54#define DBG_GET_MASK 3 /* get current debug mask of driver */
55 /* arg1: internal driver id */
56
57#define DBG_SET_MASK 4 /* set/change debug mask of driver */
58 /* arg1: internal driver id */
59 /* arg2: new debug mask */
60
61#define DBG_GET_BUFSIZE 5 /* get current buffer size of driver */
62 /* arg1: internal driver id */
63 /* arg2: new debug mask */
64
65#define DBG_SET_BUFSIZE 6 /* set new buffer size of driver */
66 /* arg1: new buffer size */
67
68/*
69 * common internal debug message structure
70 */
71
72typedef struct
73{ unsigned short id ; /* virtual driver id */
74 unsigned short type ; /* special message type */
75 unsigned long seq ; /* sequence number of message */
76 unsigned long size ; /* size of message in bytes */
77 unsigned long next ; /* offset to next buffered message */
78 LARGE_INTEGER NTtime ; /* 100 ns since 1.1.1601 */
79 unsigned char data[4] ;/* message data */
80} OldDbgMessage ;
81
82typedef struct
83{ LARGE_INTEGER NTtime ; /* 100 ns since 1.1.1601 */
84 unsigned short size ; /* size of message in bytes */
85 unsigned short ffff ; /* always 0xffff to indicate new msg */
86 unsigned short id ; /* virtual driver id */
87 unsigned short type ; /* special message type */
88 unsigned long seq ; /* sequence number of message */
89 unsigned char data[4] ;/* message data */
90} DbgMessage ;
91
92#endif
93
94#define DRV_ID_UNKNOWN 0x0C /* for messages via prtComp() */
95
96#define MSG_PROC_FLAG 0x80
97#define MSG_PROC_NO_GET(x) (((x) & MSG_PROC_FLAG) ? (((x) >> 4) & 7) : -1)
98#define MSG_PROC_NO_SET(x) (MSG_PROC_FLAG | (((x) & 7) << 4))
99
100#define MSG_TYPE_DRV_ID 0x0001
101#define MSG_TYPE_FLAGS 0x0002
102#define MSG_TYPE_STRING 0x0003
103#define MSG_TYPE_BINARY 0x0004
104
105#define MSG_HEAD_SIZE ((unsigned long)&(((DbgMessage *)0)->data[0]))
106#define MSG_ALIGN(len) (((unsigned long)(len) + MSG_HEAD_SIZE + 3) & ~3)
107#define MSG_SIZE(pMsg) MSG_ALIGN((pMsg)->size)
108#define MSG_NEXT(pMsg) ((DbgMessage *)( ((char *)(pMsg)) + MSG_SIZE(pMsg) ))
109
110#define OLD_MSG_HEAD_SIZE ((unsigned long)&(((OldDbgMessage *)0)->data[0]))
111#define OLD_MSG_ALIGN(len) (((unsigned long)(len)+OLD_MSG_HEAD_SIZE+3) & ~3)
112
113/*
114 * manifest constants
115 */
116
117#define MSG_FRAME_MAX_SIZE 2150 /* maximum size of B1 frame */
118#define MSG_TEXT_MAX_SIZE 1024 /* maximum size of msg text */
119#define MSG_MAX_SIZE MSG_ALIGN(MSG_FRAME_MAX_SIZE)
120#define DBG_MIN_BUFFER_SIZE 0x00008000 /* minimal total buffer size 32 KB */
121#define DBG_DEF_BUFFER_SIZE 0x00020000 /* default total buffer size 128 KB */
122#define DBG_MAX_BUFFER_SIZE 0x00400000 /* maximal total buffer size 4 MB */
123
124#define DBGDRV_NAME "Diehl_DIMAINT"
125#define UNIDBG_DRIVER L"\\Device\\Diehl_DIMAINT" /* UNICODE name for kernel */
126#define DEBUG_DRIVER "\\\\.\\" DBGDRV_NAME /* traditional string for apps */
127#define DBGVXD_NAME "DIMAINT"
128#define DEBUG_VXD "\\\\.\\" DBGVXD_NAME /* traditional string for apps */
129
130/*
131 * Special IDI interface debug construction
132 */
133
134#define DBG_IDI_SIG_REQ (unsigned long)0xF479C402
135#define DBG_IDI_SIG_IND (unsigned long)0xF479C403
136#define DBG_IDI_NL_REQ (unsigned long)0xF479C404
137#define DBG_IDI_NL_IND (unsigned long)0xF479C405
138
139typedef struct
140{ unsigned long magic_type ;
141 unsigned short data_len ;
142 unsigned char layer_ID ;
143 unsigned char entity_ID ;
144 unsigned char request ;
145 unsigned char ret_code ;
146 unsigned char indication ;
147 unsigned char complete ;
148 unsigned char data[4] ;
149} DbgIdiAct, *DbgIdiAction ;
150
151/*
152 * We want to use the same IOCTL codes in Win95 and WinNT.
153 * The official constructor for IOCTL codes is the CTL_CODE macro
154 * from <winoctl.h> (<devioctl.h> in WinNT DDK environment).
155 * The problem here is that we don't know how to get <winioctl.h>
156 * working in a Win95 DDK environment!
157 */
158
159# ifdef CTL_CODE /*{*/
160
161/* Assert that we have the same idea of the CTL_CODE macro. */
162
163#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
164 ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
165)
166
167# else /* !CTL_CODE */ /*}{*/
168
169/* Use the definitions stolen from <winioctl.h>. */
170
171#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
172 ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
173)
174
175#define METHOD_BUFFERED 0
176#define METHOD_IN_DIRECT 1
177#define METHOD_OUT_DIRECT 2
178#define METHOD_NEITHER 3
179
180#define FILE_ANY_ACCESS 0
181#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe
182#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe
183
184# endif /* CTL_CODE */ /*}*/
185
186/*
187 * Now we can define WinNT/Win95 DeviceIoControl codes.
188 *
189 * These codes are defined in di_defs.h too, a possible mismatch will be
190 * detected when the dbgtool is compiled.
191 */
192
193#define IOCTL_DRIVER_LNK \
194 CTL_CODE(0x8001U,0x701,METHOD_OUT_DIRECT,FILE_ANY_ACCESS)
195#define IOCTL_DRIVER_DBG \
196 CTL_CODE(0x8001U,0x702,METHOD_OUT_DIRECT,FILE_ANY_ACCESS)
197
198#endif /* __DBGIOCTL_H__ */
diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c
new file mode 100644
index 000000000000..6851c6270ce8
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/debug.c
@@ -0,0 +1,2133 @@
1#include "platform.h"
2#include "pc.h"
3#include "di_defs.h"
4#include "debug_if.h"
5#include "divasync.h"
6#include "kst_ifc.h"
7#include "maintidi.h"
8#include "man_defs.h"
9
10/*
11 LOCALS
12 */
13#define DBG_MAGIC (0x47114711L)
14
15static void DI_register (void *arg);
16static void DI_deregister (pDbgHandle hDbg);
17static void DI_format (int do_lock, word id, int type, char *format, va_list argument_list);
18static void DI_format_locked (word id, int type, char *format, va_list argument_list);
19static void DI_format_old (word id, char *format, va_list ap) { }
20static void DiProcessEventLog (unsigned short id, unsigned long msgID, va_list ap) { }
21static void single_p (byte * P, word * PLength, byte Id);
22static void diva_maint_xdi_cb (ENTITY* e);
23static word SuperTraceCreateReadReq (byte* P, const char* path);
24static int diva_mnt_cmp_nmbr (const char* nmbr);
25static void diva_free_dma_descriptor (IDI_CALL request, int nr);
26static int diva_get_dma_descriptor (IDI_CALL request, dword *dma_magic);
27void diva_mnt_internal_dprintf (dword drv_id, dword type, char* p, ...);
28
29static dword MaxDumpSize = 256 ;
30static dword MaxXlogSize = 2 + 128 ;
31static char TraceFilter[DIVA_MAX_SELECTIVE_FILTER_LENGTH+1];
32static int TraceFilterIdent = -1;
33static int TraceFilterChannel = -1;
34
35typedef struct _diva_maint_client {
36 dword sec;
37 dword usec;
38 pDbgHandle hDbg;
39 char drvName[128];
40 dword dbgMask;
41 dword last_dbgMask;
42 IDI_CALL request;
43 _DbgHandle_ Dbg;
44 int logical;
45 int channels;
46 diva_strace_library_interface_t* pIdiLib;
47 BUFFERS XData;
48 char xbuffer[2048+512];
49 byte* pmem;
50 int request_pending;
51 int dma_handle;
52} diva_maint_client_t;
53static diva_maint_client_t clients[MAX_DESCRIPTORS];
54
55static void diva_change_management_debug_mask (diva_maint_client_t* pC, dword old_mask);
56
57static void diva_maint_error (void* user_context,
58 diva_strace_library_interface_t* hLib,
59 int Adapter,
60 int error,
61 const char* file,
62 int line);
63static void diva_maint_state_change_notify (void* user_context,
64 diva_strace_library_interface_t* hLib,
65 int Adapter,
66 diva_trace_line_state_t* channel,
67 int notify_subject);
68static void diva_maint_trace_notify (void* user_context,
69 diva_strace_library_interface_t* hLib,
70 int Adapter,
71 void* xlog_buffer,
72 int length);
73
74
75
76typedef struct MSG_QUEUE {
77 dword Size; /* total size of queue (constant) */
78 byte *Base; /* lowest address (constant) */
79 byte *High; /* Base + Size (constant) */
80 byte *Head; /* first message in queue (if any) */
81 byte *Tail; /* first free position */
82 byte *Wrap; /* current wraparound position */
83 dword Count; /* current no of bytes in queue */
84} MSG_QUEUE;
85
86typedef struct MSG_HEAD {
87 volatile dword Size; /* size of data following MSG_HEAD */
88#define MSG_INCOMPLETE 0x8000 /* ored to Size until queueCompleteMsg */
89} MSG_HEAD;
90
91#define queueCompleteMsg(p) do{ ((MSG_HEAD *)p - 1)->Size &= ~MSG_INCOMPLETE; }while(0)
92#define queueCount(q) ((q)->Count)
93#define MSG_NEED(size) \
94 ( (sizeof(MSG_HEAD) + size + sizeof(dword) - 1) & ~(sizeof(dword) - 1) )
95
96static void queueInit (MSG_QUEUE *Q, byte *Buffer, dword sizeBuffer) {
97 Q->Size = sizeBuffer;
98 Q->Base = Q->Head = Q->Tail = Buffer;
99 Q->High = Buffer + sizeBuffer;
100 Q->Wrap = NULL;
101 Q->Count= 0;
102}
103
104static byte *queueAllocMsg (MSG_QUEUE *Q, word size) {
105 /* Allocate 'size' bytes at tail of queue which will be filled later
106 * directly with callers own message header info and/or message.
107 * An 'alloced' message is marked incomplete by oring the 'Size' field
108 * with MSG_INCOMPLETE.
109 * This must be reset via queueCompleteMsg() after the message is filled.
110 * As long as a message is marked incomplete queuePeekMsg() will return
111 * a 'queue empty' condition when it reaches such a message. */
112
113 MSG_HEAD *Msg;
114 word need = MSG_NEED(size);
115
116 if (Q->Tail == Q->Head) {
117 if (Q->Wrap || need > Q->Size) {
118 return NULL; /* full */
119 }
120 goto alloc; /* empty */
121 }
122
123 if (Q->Tail > Q->Head) {
124 if (Q->Tail + need <= Q->High) goto alloc; /* append */
125 if (Q->Base + need > Q->Head) {
126 return NULL; /* too much */
127 }
128 /* wraparound the queue (but not the message) */
129 Q->Wrap = Q->Tail;
130 Q->Tail = Q->Base;
131 goto alloc;
132 }
133
134 if (Q->Tail + need > Q->Head) {
135 return NULL; /* too much */
136 }
137
138alloc:
139 Msg = (MSG_HEAD *)Q->Tail;
140
141 Msg->Size = size | MSG_INCOMPLETE;
142
143 Q->Tail += need;
144 Q->Count += size;
145
146
147
148 return ((byte*)(Msg + 1));
149}
150
151static void queueFreeMsg (MSG_QUEUE *Q) {
152/* Free the message at head of queue */
153
154 word size = ((MSG_HEAD *)Q->Head)->Size & ~MSG_INCOMPLETE;
155
156 Q->Head += MSG_NEED(size);
157 Q->Count -= size;
158
159 if (Q->Wrap) {
160 if (Q->Head >= Q->Wrap) {
161 Q->Head = Q->Base;
162 Q->Wrap = NULL;
163 }
164 } else if (Q->Head >= Q->Tail) {
165 Q->Head = Q->Tail = Q->Base;
166 }
167}
168
169static byte *queuePeekMsg (MSG_QUEUE *Q, word *size) {
170 /* Show the first valid message in queue BUT DON'T free the message.
171 * After looking on the message contents it can be freed queueFreeMsg()
172 * or simply remain in message queue. */
173
174 MSG_HEAD *Msg = (MSG_HEAD *)Q->Head;
175
176 if (((byte *)Msg == Q->Tail && !Q->Wrap) ||
177 (Msg->Size & MSG_INCOMPLETE)) {
178 return NULL;
179 } else {
180 *size = Msg->Size;
181 return ((byte *)(Msg + 1));
182 }
183}
184
185/*
186 Message queue header
187 */
188static MSG_QUEUE* dbg_queue;
189static byte* dbg_base;
190static int external_dbg_queue;
191static diva_os_spin_lock_t dbg_q_lock;
192static diva_os_spin_lock_t dbg_adapter_lock;
193static int dbg_q_busy;
194static volatile dword dbg_sequence;
195static dword start_sec;
196static dword start_usec;
197
198/*
199 INTERFACE:
200 Initialize run time queue structures.
201 base: base of the message queue
202 length: length of the message queue
203 do_init: perfor queue reset
204
205 return: zero on success, -1 on error
206 */
207int diva_maint_init (byte* base, unsigned long length, int do_init) {
208 if (dbg_queue || (!base) || (length < (4096*4))) {
209 return (-1);
210 }
211
212 TraceFilter[0] = 0;
213 TraceFilterIdent = -1;
214 TraceFilterChannel = -1;
215
216 dbg_base = base;
217
218 diva_os_get_time (&start_sec, &start_usec);
219
220 *(dword*)base = (dword)DBG_MAGIC; /* Store Magic */
221 base += sizeof(dword);
222 length -= sizeof(dword);
223
224 *(dword*)base = 2048; /* Extension Field Length */
225 base += sizeof(dword);
226 length -= sizeof(dword);
227
228 strcpy (base, "KERNEL MODE BUFFER\n");
229 base += 2048;
230 length -= 2048;
231
232 *(dword*)base = 0; /* Terminate extension */
233 base += sizeof(dword);
234 length -= sizeof(dword);
235
236 *(void**)base = (void*)(base+sizeof(void*)); /* Store Base */
237 base += sizeof(void*);
238 length -= sizeof(void*);
239
240 dbg_queue = (MSG_QUEUE*)base;
241 queueInit (dbg_queue, base + sizeof(MSG_QUEUE), length - sizeof(MSG_QUEUE) - 512);
242 external_dbg_queue = 0;
243
244 if (!do_init) {
245 external_dbg_queue = 1; /* memory was located on the external device */
246 }
247
248
249 if (diva_os_initialize_spin_lock (&dbg_q_lock, "dbg_init")) {
250 dbg_queue = NULL;
251 dbg_base = NULL;
252 external_dbg_queue = 0;
253 return (-1);
254 }
255
256 if (diva_os_initialize_spin_lock (&dbg_adapter_lock, "dbg_init")) {
257 diva_os_destroy_spin_lock(&dbg_q_lock, "dbg_init");
258 dbg_queue = NULL;
259 dbg_base = NULL;
260 external_dbg_queue = 0;
261 return (-1);
262 }
263
264 return (0);
265}
266
267/*
268 INTERFACE:
269 Finit at unload time
270 return address of internal queue or zero if queue
271 was external
272 */
273void* diva_maint_finit (void) {
274 void* ret = (void*)dbg_base;
275 int i;
276
277 dbg_queue = NULL;
278 dbg_base = NULL;
279
280 if (ret) {
281 diva_os_destroy_spin_lock(&dbg_q_lock, "dbg_finit");
282 diva_os_destroy_spin_lock(&dbg_adapter_lock, "dbg_finit");
283 }
284
285 if (external_dbg_queue) {
286 ret = NULL;
287 }
288 external_dbg_queue = 0;
289
290 for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
291 if (clients[i].pmem) {
292 diva_os_free (0, clients[i].pmem);
293 }
294 }
295
296 return (ret);
297}
298
299/*
300 INTERFACE:
301 Return amount of messages in debug queue
302 */
303dword diva_dbg_q_length (void) {
304 return (dbg_queue ? queueCount(dbg_queue) : 0);
305}
306
307/*
308 INTERFACE:
309 Lock message queue and return the pointer to the first
310 entry.
311 */
312diva_dbg_entry_head_t* diva_maint_get_message (word* size,
313 diva_os_spin_lock_magic_t* old_irql) {
314 diva_dbg_entry_head_t* pmsg = NULL;
315
316 diva_os_enter_spin_lock (&dbg_q_lock, old_irql, "read");
317 if (dbg_q_busy) {
318 diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_busy");
319 return NULL;
320 }
321 dbg_q_busy = 1;
322
323 if (!(pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, size))) {
324 dbg_q_busy = 0;
325 diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_empty");
326 }
327
328 return (pmsg);
329}
330
331/*
332 INTERFACE:
333 acknowledge last message and unlock queue
334 */
335void diva_maint_ack_message (int do_release,
336 diva_os_spin_lock_magic_t* old_irql) {
337 if (!dbg_q_busy) {
338 return;
339 }
340 if (do_release) {
341 queueFreeMsg (dbg_queue);
342 }
343 dbg_q_busy = 0;
344 diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_ack");
345}
346
347
348/*
349 INTERFACE:
350 PRT COMP function used to register
351 with MAINT adapter or log in compatibility
352 mode in case older driver version is connected too
353 */
354void diva_maint_prtComp (char *format, ...) {
355 void *hDbg;
356 va_list ap;
357
358 if (!format)
359 return;
360
361 va_start(ap, format);
362
363 /*
364 register to new log driver functions
365 */
366 if ((format[0] == 0) && ((unsigned char)format[1] == 255)) {
367 hDbg = va_arg(ap, void *); /* ptr to DbgHandle */
368 DI_register (hDbg);
369 }
370
371 va_end (ap);
372}
373
374static void DI_register (void *arg) {
375 diva_os_spin_lock_magic_t old_irql;
376 dword sec, usec;
377 pDbgHandle hDbg ;
378 int id, free_id = -1, best_id = 0;
379
380 diva_os_get_time (&sec, &usec);
381
382 hDbg = (pDbgHandle)arg ;
383 /*
384 Check for bad args, specially for the old obsolete debug handle
385 */
386 if ((hDbg == NULL) ||
387 ((hDbg->id == 0) && (((_OldDbgHandle_ *)hDbg)->id == -1)) ||
388 (hDbg->Registered != 0)) {
389 return ;
390 }
391
392 diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "register");
393
394 for (id = 1; id < (sizeof(clients)/sizeof(clients[0])); id++) {
395 if (clients[id].hDbg == hDbg) {
396 /*
397 driver already registered
398 */
399 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
400 return;
401 }
402 if (clients[id].hDbg) { /* slot is busy */
403 continue;
404 }
405 free_id = id;
406 if (!strcmp (clients[id].drvName, hDbg->drvName)) {
407 /*
408 This driver was already registered with this name
409 and slot is still free - reuse it
410 */
411 best_id = 1;
412 break;
413 }
414 if (!clients[id].hDbg) { /* slot is busy */
415 break;
416 }
417 }
418
419 if (free_id != -1) {
420 diva_dbg_entry_head_t* pmsg = NULL;
421 int len;
422 char tmp[256];
423 word size;
424
425 /*
426 Register new driver with id == free_id
427 */
428 clients[free_id].hDbg = hDbg;
429 clients[free_id].sec = sec;
430 clients[free_id].usec = usec;
431 strcpy (clients[free_id].drvName, hDbg->drvName);
432
433 clients[free_id].dbgMask = hDbg->dbgMask;
434 if (best_id) {
435 hDbg->dbgMask |= clients[free_id].last_dbgMask;
436 } else {
437 clients[free_id].last_dbgMask = 0;
438 }
439
440 hDbg->Registered = DBG_HANDLE_REG_NEW ;
441 hDbg->id = (byte)free_id;
442 hDbg->dbg_end = DI_deregister;
443 hDbg->dbg_prt = DI_format_locked;
444 hDbg->dbg_ev = DiProcessEventLog;
445 hDbg->dbg_irq = DI_format_locked;
446 if (hDbg->Version > 0) {
447 hDbg->dbg_old = DI_format_old;
448 }
449 hDbg->next = (pDbgHandle)DBG_MAGIC;
450
451 /*
452 Log driver register, MAINT driver ID is '0'
453 */
454 len = sprintf (tmp, "DIMAINT - drv # %d = '%s' registered",
455 free_id, hDbg->drvName);
456
457 while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue,
458 (word)(len+1+sizeof(*pmsg))))) {
459 if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) {
460 queueFreeMsg (dbg_queue);
461 } else {
462 break;
463 }
464 }
465
466 if (pmsg) {
467 pmsg->sequence = dbg_sequence++;
468 pmsg->time_sec = sec;
469 pmsg->time_usec = usec;
470 pmsg->facility = MSG_TYPE_STRING;
471 pmsg->dli = DLI_REG;
472 pmsg->drv_id = 0; /* id 0 - DIMAINT */
473 pmsg->di_cpu = 0;
474 pmsg->data_length = len+1;
475
476 memcpy (&pmsg[1], tmp, len+1);
477 queueCompleteMsg (pmsg);
478 diva_maint_wakeup_read();
479 }
480 }
481
482 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
483}
484
485static void DI_deregister (pDbgHandle hDbg) {
486 diva_os_spin_lock_magic_t old_irql, old_irql1;
487 dword sec, usec;
488 int i;
489 word size;
490 byte* pmem = NULL;
491
492 diva_os_get_time (&sec, &usec);
493
494 diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read");
495 diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read");
496
497 for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
498 if (clients[i].hDbg == hDbg) {
499 diva_dbg_entry_head_t* pmsg;
500 char tmp[256];
501 int len;
502
503 clients[i].hDbg = NULL;
504
505 hDbg->id = -1;
506 hDbg->dbgMask = 0;
507 hDbg->dbg_end = NULL;
508 hDbg->dbg_prt = NULL;
509 hDbg->dbg_irq = NULL;
510 if (hDbg->Version > 0)
511 hDbg->dbg_old = NULL;
512 hDbg->Registered = 0;
513 hDbg->next = NULL;
514
515 if (clients[i].pIdiLib) {
516 (*(clients[i].pIdiLib->DivaSTraceLibraryFinit))(clients[i].pIdiLib->hLib);
517 clients[i].pIdiLib = NULL;
518
519 pmem = clients[i].pmem;
520 clients[i].pmem = NULL;
521 }
522
523 /*
524 Log driver register, MAINT driver ID is '0'
525 */
526 len = sprintf (tmp, "DIMAINT - drv # %d = '%s' de-registered",
527 i, hDbg->drvName);
528
529 while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue,
530 (word)(len+1+sizeof(*pmsg))))) {
531 if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) {
532 queueFreeMsg (dbg_queue);
533 } else {
534 break;
535 }
536 }
537
538 if (pmsg) {
539 pmsg->sequence = dbg_sequence++;
540 pmsg->time_sec = sec;
541 pmsg->time_usec = usec;
542 pmsg->facility = MSG_TYPE_STRING;
543 pmsg->dli = DLI_REG;
544 pmsg->drv_id = 0; /* id 0 - DIMAINT */
545 pmsg->di_cpu = 0;
546 pmsg->data_length = len+1;
547
548 memcpy (&pmsg[1], tmp, len+1);
549 queueCompleteMsg (pmsg);
550 diva_maint_wakeup_read();
551 }
552
553 break;
554 }
555 }
556
557 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_ack");
558 diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "read_ack");
559
560 if (pmem) {
561 diva_os_free (0, pmem);
562 }
563}
564
565static void DI_format_locked (unsigned short id,
566 int type,
567 char *format,
568 va_list argument_list) {
569 DI_format (1, id, type, format, argument_list);
570}
571
572static void DI_format (int do_lock,
573 unsigned short id,
574 int type,
575 char *format,
576 va_list ap) {
577 diva_os_spin_lock_magic_t old_irql;
578 dword sec, usec;
579 diva_dbg_entry_head_t* pmsg = NULL;
580 dword length;
581 word size;
582 static char fmtBuf[MSG_FRAME_MAX_SIZE+sizeof(*pmsg)+1];
583 char *data;
584 unsigned short code;
585
586 if (diva_os_in_irq()) {
587 dbg_sequence++;
588 return;
589 }
590
591 if ((!format) ||
592 ((TraceFilter[0] != 0) && ((TraceFilterIdent < 0) || (TraceFilterChannel < 0)))) {
593 return;
594 }
595
596
597
598 diva_os_get_time (&sec, &usec);
599
600 if (do_lock) {
601 diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "format");
602 }
603
604 switch (type) {
605 case DLI_MXLOG :
606 case DLI_BLK :
607 case DLI_SEND:
608 case DLI_RECV:
609 if (!(length = va_arg(ap, unsigned long))) {
610 break;
611 }
612 if (length > MaxDumpSize) {
613 length = MaxDumpSize;
614 }
615 while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue,
616 (word)length+sizeof(*pmsg)))) {
617 if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) {
618 queueFreeMsg (dbg_queue);
619 } else {
620 break;
621 }
622 }
623 if (pmsg) {
624 memcpy (&pmsg[1], format, length);
625 pmsg->sequence = dbg_sequence++;
626 pmsg->time_sec = sec;
627 pmsg->time_usec = usec;
628 pmsg->facility = MSG_TYPE_BINARY ;
629 pmsg->dli = type; /* DLI_XXX */
630 pmsg->drv_id = id; /* driver MAINT id */
631 pmsg->di_cpu = 0;
632 pmsg->data_length = length;
633 queueCompleteMsg (pmsg);
634 }
635 break;
636
637 case DLI_XLOG: {
638 byte* p;
639 data = va_arg(ap, char*);
640 code = (unsigned short)va_arg(ap, unsigned int);
641 length = (unsigned long) va_arg(ap, unsigned int);
642
643 if (length > MaxXlogSize)
644 length = MaxXlogSize;
645
646 while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue,
647 (word)length+sizeof(*pmsg)+2))) {
648 if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) {
649 queueFreeMsg (dbg_queue);
650 } else {
651 break;
652 }
653 }
654 if (pmsg) {
655 p = (byte*)&pmsg[1];
656 p[0] = (char)(code) ;
657 p[1] = (char)(code >> 8) ;
658 if (data && length) {
659 memcpy (&p[2], &data[0], length) ;
660 }
661 length += 2 ;
662
663 pmsg->sequence = dbg_sequence++;
664 pmsg->time_sec = sec;
665 pmsg->time_usec = usec;
666 pmsg->facility = MSG_TYPE_BINARY ;
667 pmsg->dli = type; /* DLI_XXX */
668 pmsg->drv_id = id; /* driver MAINT id */
669 pmsg->di_cpu = 0;
670 pmsg->data_length = length;
671 queueCompleteMsg (pmsg);
672 }
673 } break;
674
675 case DLI_LOG :
676 case DLI_FTL :
677 case DLI_ERR :
678 case DLI_TRC :
679 case DLI_REG :
680 case DLI_MEM :
681 case DLI_SPL :
682 case DLI_IRP :
683 case DLI_TIM :
684 case DLI_TAPI:
685 case DLI_NDIS:
686 case DLI_CONN:
687 case DLI_STAT:
688 case DLI_PRV0:
689 case DLI_PRV1:
690 case DLI_PRV2:
691 case DLI_PRV3:
692 if ((length = (unsigned long)vsprintf (&fmtBuf[0], format, ap)) > 0) {
693 length += (sizeof(*pmsg)+1);
694
695 while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue,
696 (word)length))) {
697 if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) {
698 queueFreeMsg (dbg_queue);
699 } else {
700 break;
701 }
702 }
703
704 pmsg->sequence = dbg_sequence++;
705 pmsg->time_sec = sec;
706 pmsg->time_usec = usec;
707 pmsg->facility = MSG_TYPE_STRING;
708 pmsg->dli = type; /* DLI_XXX */
709 pmsg->drv_id = id; /* driver MAINT id */
710 pmsg->di_cpu = 0;
711 pmsg->data_length = length - sizeof(*pmsg);
712
713 memcpy (&pmsg[1], fmtBuf, pmsg->data_length);
714 queueCompleteMsg (pmsg);
715 }
716 break;
717
718 } /* switch type */
719
720
721 if (queueCount(dbg_queue)) {
722 diva_maint_wakeup_read();
723 }
724
725 if (do_lock) {
726 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "format");
727 }
728}
729
730/*
731 Write driver ID and driver revision to callers buffer
732 */
733int diva_get_driver_info (dword id, byte* data, int data_length) {
734 diva_os_spin_lock_magic_t old_irql;
735 byte* p = data;
736 int to_copy;
737
738 if (!data || !id || (data_length < 17) ||
739 (id >= (sizeof(clients)/sizeof(clients[0])))) {
740 return (-1);
741 }
742
743 diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "driver info");
744
745 if (clients[id].hDbg) {
746 *p++ = 1;
747 *p++ = (byte)clients[id].sec; /* save seconds */
748 *p++ = (byte)(clients[id].sec >> 8);
749 *p++ = (byte)(clients[id].sec >> 16);
750 *p++ = (byte)(clients[id].sec >> 24);
751
752 *p++ = (byte)(clients[id].usec/1000); /* save mseconds */
753 *p++ = (byte)((clients[id].usec/1000) >> 8);
754 *p++ = (byte)((clients[id].usec/1000) >> 16);
755 *p++ = (byte)((clients[id].usec/1000) >> 24);
756
757 data_length -= 9;
758
759 if ((to_copy = MIN(strlen(clients[id].drvName), data_length-1))) {
760 memcpy (p, clients[id].drvName, to_copy);
761 p += to_copy;
762 data_length -= to_copy;
763 if ((data_length >= 4) && clients[id].hDbg->drvTag[0]) {
764 *p++ = '(';
765 data_length -= 1;
766 if ((to_copy = MIN(strlen(clients[id].hDbg->drvTag), data_length-2))) {
767 memcpy (p, clients[id].hDbg->drvTag, to_copy);
768 p += to_copy;
769 data_length -= to_copy;
770 if (data_length >= 2) {
771 *p++ = ')';
772 data_length--;
773 }
774 }
775 }
776 }
777 }
778 *p++ = 0;
779
780 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "driver info");
781
782 return (p - data);
783}
784
785int diva_get_driver_dbg_mask (dword id, byte* data) {
786 diva_os_spin_lock_magic_t old_irql;
787 int ret = -1;
788
789 if (!data || !id || (id >= (sizeof(clients)/sizeof(clients[0])))) {
790 return (-1);
791 }
792 diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "driver info");
793
794 if (clients[id].hDbg) {
795 ret = 4;
796 *data++= (byte)(clients[id].hDbg->dbgMask);
797 *data++= (byte)(clients[id].hDbg->dbgMask >> 8);
798 *data++= (byte)(clients[id].hDbg->dbgMask >> 16);
799 *data++= (byte)(clients[id].hDbg->dbgMask >> 24);
800 }
801
802 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "driver info");
803
804 return (ret);
805}
806
807int diva_set_driver_dbg_mask (dword id, dword mask) {
808 diva_os_spin_lock_magic_t old_irql, old_irql1;
809 int ret = -1;
810
811
812 if (!id || (id >= (sizeof(clients)/sizeof(clients[0])))) {
813 return (-1);
814 }
815
816 diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
817 diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "dbg mask");
818
819 if (clients[id].hDbg) {
820 dword old_mask = clients[id].hDbg->dbgMask;
821 mask &= 0x7fffffff;
822 clients[id].hDbg->dbgMask = mask;
823 clients[id].last_dbgMask = (clients[id].hDbg->dbgMask | clients[id].dbgMask);
824 ret = 4;
825 diva_change_management_debug_mask (&clients[id], old_mask);
826 }
827
828
829 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "dbg mask");
830
831 if (clients[id].request_pending) {
832 clients[id].request_pending = 0;
833 (*(clients[id].request))((ENTITY*)(*(clients[id].pIdiLib->DivaSTraceGetHandle))(clients[id].pIdiLib->hLib));
834 }
835
836 diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
837
838 return (ret);
839}
840
841static int diva_get_idi_adapter_info (IDI_CALL request, dword* serial, dword* logical) {
842 IDI_SYNC_REQ sync_req;
843
844 sync_req.xdi_logical_adapter_number.Req = 0;
845 sync_req.xdi_logical_adapter_number.Rc = IDI_SYNC_REQ_XDI_GET_LOGICAL_ADAPTER_NUMBER;
846 (*request)((ENTITY *)&sync_req);
847 *logical = sync_req.xdi_logical_adapter_number.info.logical_adapter_number;
848
849 sync_req.GetSerial.Req = 0;
850 sync_req.GetSerial.Rc = IDI_SYNC_REQ_GET_SERIAL;
851 sync_req.GetSerial.serial = 0;
852 (*request)((ENTITY *)&sync_req);
853 *serial = sync_req.GetSerial.serial;
854
855 return (0);
856}
857
858/*
859 Register XDI adapter as MAINT compatible driver
860 */
861void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) {
862 diva_os_spin_lock_magic_t old_irql, old_irql1;
863 dword sec, usec, logical, serial, org_mask;
864 int id, best_id = 0, free_id = -1;
865 char tmp[256];
866 diva_dbg_entry_head_t* pmsg = NULL;
867 int len;
868 word size;
869 byte* pmem;
870
871 diva_os_get_time (&sec, &usec);
872 diva_get_idi_adapter_info (d->request, &serial, &logical);
873 if (serial & 0xff000000) {
874 sprintf (tmp, "ADAPTER:%d SN:%u-%d",
875 (int)logical,
876 serial & 0x00ffffff,
877 (byte)(((serial & 0xff000000) >> 24) + 1));
878 } else {
879 sprintf (tmp, "ADAPTER:%d SN:%u", (int)logical, serial);
880 }
881
882 if (!(pmem = diva_os_malloc (0, DivaSTraceGetMemotyRequirement (d->channels)))) {
883 return;
884 }
885 memset (pmem, 0x00, DivaSTraceGetMemotyRequirement (d->channels));
886
887 diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
888 diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "register");
889
890 for (id = 1; id < (sizeof(clients)/sizeof(clients[0])); id++) {
891 if (clients[id].hDbg && (clients[id].request == d->request)) {
892 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
893 diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
894 diva_os_free(0, pmem);
895 return;
896 }
897 if (clients[id].hDbg) { /* slot is busy */
898 continue;
899 }
900 if (free_id < 0) {
901 free_id = id;
902 }
903 if (!strcmp (clients[id].drvName, tmp)) {
904 /*
905 This driver was already registered with this name
906 and slot is still free - reuse it
907 */
908 free_id = id;
909 best_id = 1;
910 break;
911 }
912 }
913
914 if (free_id < 0) {
915 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
916 diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
917 diva_os_free (0, pmem);
918 return;
919 }
920
921 id = free_id;
922 clients[id].request = d->request;
923 clients[id].request_pending = 0;
924 clients[id].hDbg = &clients[id].Dbg;
925 clients[id].sec = sec;
926 clients[id].usec = usec;
927 strcpy (clients[id].drvName, tmp);
928 strcpy (clients[id].Dbg.drvName, tmp);
929 clients[id].Dbg.drvTag[0] = 0;
930 clients[id].logical = (int)logical;
931 clients[id].channels = (int)d->channels;
932 clients[id].dma_handle = -1;
933
934 clients[id].Dbg.dbgMask = 0;
935 clients[id].dbgMask = clients[id].Dbg.dbgMask;
936 if (id) {
937 clients[id].Dbg.dbgMask |= clients[free_id].last_dbgMask;
938 } else {
939 clients[id].last_dbgMask = 0;
940 }
941 clients[id].Dbg.Registered = DBG_HANDLE_REG_NEW;
942 clients[id].Dbg.id = (byte)id;
943 clients[id].Dbg.dbg_end = DI_deregister;
944 clients[id].Dbg.dbg_prt = DI_format_locked;
945 clients[id].Dbg.dbg_ev = DiProcessEventLog;
946 clients[id].Dbg.dbg_irq = DI_format_locked;
947 clients[id].Dbg.next = (pDbgHandle)DBG_MAGIC;
948
949 {
950 diva_trace_library_user_interface_t diva_maint_user_ifc = { &clients[id],
951 diva_maint_state_change_notify,
952 diva_maint_trace_notify,
953 diva_maint_error };
954
955 /*
956 Attach to adapter management interface
957 */
958 if ((clients[id].pIdiLib =
959 DivaSTraceLibraryCreateInstance ((int)logical, &diva_maint_user_ifc, pmem))) {
960 if (((*(clients[id].pIdiLib->DivaSTraceLibraryStart))(clients[id].pIdiLib->hLib))) {
961 diva_mnt_internal_dprintf (0, DLI_ERR, "Adapter(%d) Start failed", (int)logical);
962 (*(clients[id].pIdiLib->DivaSTraceLibraryFinit))(clients[id].pIdiLib->hLib);
963 clients[id].pIdiLib = NULL;
964 }
965 } else {
966 diva_mnt_internal_dprintf (0, DLI_ERR, "A(%d) management init failed", (int)logical);
967 }
968 }
969
970 if (!clients[id].pIdiLib) {
971 clients[id].request = NULL;
972 clients[id].request_pending = 0;
973 clients[id].hDbg = NULL;
974 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
975 diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
976 diva_os_free (0, pmem);
977 return;
978 }
979
980 /*
981 Log driver register, MAINT driver ID is '0'
982 */
983 len = sprintf (tmp, "DIMAINT - drv # %d = '%s' registered",
984 id, clients[id].Dbg.drvName);
985
986 while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue,
987 (word)(len+1+sizeof(*pmsg))))) {
988 if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) {
989 queueFreeMsg (dbg_queue);
990 } else {
991 break;
992 }
993 }
994
995 if (pmsg) {
996 pmsg->sequence = dbg_sequence++;
997 pmsg->time_sec = sec;
998 pmsg->time_usec = usec;
999 pmsg->facility = MSG_TYPE_STRING;
1000 pmsg->dli = DLI_REG;
1001 pmsg->drv_id = 0; /* id 0 - DIMAINT */
1002 pmsg->di_cpu = 0;
1003 pmsg->data_length = len+1;
1004
1005 memcpy (&pmsg[1], tmp, len+1);
1006 queueCompleteMsg (pmsg);
1007 diva_maint_wakeup_read();
1008 }
1009
1010 org_mask = clients[id].Dbg.dbgMask;
1011 clients[id].Dbg.dbgMask = 0;
1012
1013 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
1014
1015 if (clients[id].request_pending) {
1016 clients[id].request_pending = 0;
1017 (*(clients[id].request))((ENTITY*)(*(clients[id].pIdiLib->DivaSTraceGetHandle))(clients[id].pIdiLib->hLib));
1018 }
1019
1020 diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
1021
1022 diva_set_driver_dbg_mask (id, org_mask);
1023}
1024
1025/*
1026 De-Register XDI adapter
1027 */
1028void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d) {
1029 diva_os_spin_lock_magic_t old_irql, old_irql1;
1030 dword sec, usec;
1031 int i;
1032 word size;
1033 byte* pmem = NULL;
1034
1035 diva_os_get_time (&sec, &usec);
1036
1037 diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read");
1038 diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read");
1039
1040 for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
1041 if (clients[i].hDbg && (clients[i].request == d->request)) {
1042 diva_dbg_entry_head_t* pmsg;
1043 char tmp[256];
1044 int len;
1045
1046 if (clients[i].pIdiLib) {
1047 (*(clients[i].pIdiLib->DivaSTraceLibraryFinit))(clients[i].pIdiLib->hLib);
1048 clients[i].pIdiLib = NULL;
1049
1050 pmem = clients[i].pmem;
1051 clients[i].pmem = NULL;
1052 }
1053
1054 clients[i].hDbg = NULL;
1055 clients[i].request_pending = 0;
1056 if (clients[i].dma_handle >= 0) {
1057 /*
1058 Free DMA handle
1059 */
1060 diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle);
1061 clients[i].dma_handle = -1;
1062 }
1063 clients[i].request = NULL;
1064
1065 /*
1066 Log driver register, MAINT driver ID is '0'
1067 */
1068 len = sprintf (tmp, "DIMAINT - drv # %d = '%s' de-registered",
1069 i, clients[i].Dbg.drvName);
1070
1071 memset (&clients[i].Dbg, 0x00, sizeof(clients[i].Dbg));
1072
1073 while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue,
1074 (word)(len+1+sizeof(*pmsg))))) {
1075 if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) {
1076 queueFreeMsg (dbg_queue);
1077 } else {
1078 break;
1079 }
1080 }
1081
1082 if (pmsg) {
1083 pmsg->sequence = dbg_sequence++;
1084 pmsg->time_sec = sec;
1085 pmsg->time_usec = usec;
1086 pmsg->facility = MSG_TYPE_STRING;
1087 pmsg->dli = DLI_REG;
1088 pmsg->drv_id = 0; /* id 0 - DIMAINT */
1089 pmsg->di_cpu = 0;
1090 pmsg->data_length = len+1;
1091
1092 memcpy (&pmsg[1], tmp, len+1);
1093 queueCompleteMsg (pmsg);
1094 diva_maint_wakeup_read();
1095 }
1096
1097 break;
1098 }
1099 }
1100
1101 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_ack");
1102 diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "read_ack");
1103
1104 if (pmem) {
1105 diva_os_free (0, pmem);
1106 }
1107}
1108
1109/* ----------------------------------------------------------------
1110 Low level interface for management interface client
1111 ---------------------------------------------------------------- */
1112/*
1113 Return handle to client structure
1114 */
1115void* SuperTraceOpenAdapter (int AdapterNumber) {
1116 int i;
1117
1118 for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
1119 if (clients[i].hDbg && clients[i].request && (clients[i].logical == AdapterNumber)) {
1120 return (&clients[i]);
1121 }
1122 }
1123
1124 return NULL;
1125}
1126
1127int SuperTraceCloseAdapter (void* AdapterHandle) {
1128 return (0);
1129}
1130
1131int SuperTraceReadRequest (void* AdapterHandle, const char* name, byte* data) {
1132 diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle;
1133
1134 if (pC && pC->pIdiLib && pC->request) {
1135 ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1136 byte* xdata = (byte*)&pC->xbuffer[0];
1137 char tmp = 0;
1138 word length;
1139
1140 if (!strcmp(name, "\\")) { /* Read ROOT */
1141 name = &tmp;
1142 }
1143 length = SuperTraceCreateReadReq (xdata, name);
1144 single_p (xdata, &length, 0); /* End Of Message */
1145
1146 e->Req = MAN_READ;
1147 e->ReqCh = 0;
1148 e->X->PLength = length;
1149 e->X->P = (byte*)xdata;
1150
1151 pC->request_pending = 1;
1152
1153 return (0);
1154 }
1155
1156 return (-1);
1157}
1158
1159int SuperTraceGetNumberOfChannels (void* AdapterHandle) {
1160 if (AdapterHandle) {
1161 diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle;
1162
1163 return (pC->channels);
1164 }
1165
1166 return (0);
1167}
1168
1169int SuperTraceASSIGN (void* AdapterHandle, byte* data) {
1170 diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle;
1171
1172 if (pC && pC->pIdiLib && pC->request) {
1173 ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1174 IDI_SYNC_REQ* preq;
1175 char buffer[((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
1176 char features[4];
1177 word assign_data_length = 1;
1178
1179 features[0] = 0;
1180 pC->xbuffer[0] = 0;
1181 preq = (IDI_SYNC_REQ*)&buffer[0];
1182 preq->xdi_extended_features.Req = 0;
1183 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
1184 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
1185 preq->xdi_extended_features.info.features = &features[0];
1186
1187 (*(pC->request))((ENTITY*)preq);
1188
1189 if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) &&
1190 (features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) {
1191 dword rx_dma_magic;
1192 if ((pC->dma_handle = diva_get_dma_descriptor (pC->request, &rx_dma_magic)) >= 0) {
1193 pC->xbuffer[0] = LLI;
1194 pC->xbuffer[1] = 8;
1195 pC->xbuffer[2] = 0x40;
1196 pC->xbuffer[3] = (byte)pC->dma_handle;
1197 pC->xbuffer[4] = (byte)rx_dma_magic;
1198 pC->xbuffer[5] = (byte)(rx_dma_magic >> 8);
1199 pC->xbuffer[6] = (byte)(rx_dma_magic >> 16);
1200 pC->xbuffer[7] = (byte)(rx_dma_magic >> 24);
1201 pC->xbuffer[8] = (byte)DIVA_MAX_MANAGEMENT_TRANSFER_SIZE;
1202 pC->xbuffer[9] = (byte)(DIVA_MAX_MANAGEMENT_TRANSFER_SIZE >> 8);
1203 pC->xbuffer[10] = 0;
1204
1205 assign_data_length = 11;
1206 }
1207 } else {
1208 pC->dma_handle = -1;
1209 }
1210
1211 e->Id = MAN_ID;
1212 e->callback = diva_maint_xdi_cb;
1213 e->XNum = 1;
1214 e->X = &pC->XData;
1215 e->Req = ASSIGN;
1216 e->ReqCh = 0;
1217 e->X->PLength = assign_data_length;
1218 e->X->P = (byte*)&pC->xbuffer[0];
1219
1220 pC->request_pending = 1;
1221
1222 return (0);
1223 }
1224
1225 return (-1);
1226}
1227
1228int SuperTraceREMOVE (void* AdapterHandle) {
1229 diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle;
1230
1231 if (pC && pC->pIdiLib && pC->request) {
1232 ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1233
1234 e->XNum = 1;
1235 e->X = &pC->XData;
1236 e->Req = REMOVE;
1237 e->ReqCh = 0;
1238 e->X->PLength = 1;
1239 e->X->P = (byte*)&pC->xbuffer[0];
1240 pC->xbuffer[0] = 0;
1241
1242 pC->request_pending = 1;
1243
1244 return (0);
1245 }
1246
1247 return (-1);
1248}
1249
1250int SuperTraceTraceOnRequest(void* hAdapter, const char* name, byte* data) {
1251 diva_maint_client_t* pC = (diva_maint_client_t*)hAdapter;
1252
1253 if (pC && pC->pIdiLib && pC->request) {
1254 ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1255 byte* xdata = (byte*)&pC->xbuffer[0];
1256 char tmp = 0;
1257 word length;
1258
1259 if (!strcmp(name, "\\")) { /* Read ROOT */
1260 name = &tmp;
1261 }
1262 length = SuperTraceCreateReadReq (xdata, name);
1263 single_p (xdata, &length, 0); /* End Of Message */
1264 e->Req = MAN_EVENT_ON;
1265 e->ReqCh = 0;
1266 e->X->PLength = length;
1267 e->X->P = (byte*)xdata;
1268
1269 pC->request_pending = 1;
1270
1271 return (0);
1272 }
1273
1274 return (-1);
1275}
1276
1277int SuperTraceWriteVar (void* AdapterHandle,
1278 byte* data,
1279 const char* name,
1280 void* var,
1281 byte type,
1282 byte var_length) {
1283 diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle;
1284
1285 if (pC && pC->pIdiLib && pC->request) {
1286 ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1287 diva_man_var_header_t* pVar = (diva_man_var_header_t*)&pC->xbuffer[0];
1288 word length = SuperTraceCreateReadReq ((byte*)pVar, name);
1289
1290 memcpy (&pC->xbuffer[length], var, var_length);
1291 length += var_length;
1292 pVar->length += var_length;
1293 pVar->value_length = var_length;
1294 pVar->type = type;
1295 single_p ((byte*)pVar, &length, 0); /* End Of Message */
1296
1297 e->Req = MAN_WRITE;
1298 e->ReqCh = 0;
1299 e->X->PLength = length;
1300 e->X->P = (byte*)pVar;
1301
1302 pC->request_pending = 1;
1303
1304 return (0);
1305 }
1306
1307 return (-1);
1308}
1309
1310int SuperTraceExecuteRequest (void* AdapterHandle,
1311 const char* name,
1312 byte* data) {
1313 diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle;
1314
1315 if (pC && pC->pIdiLib && pC->request) {
1316 ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1317 byte* xdata = (byte*)&pC->xbuffer[0];
1318 word length;
1319
1320 length = SuperTraceCreateReadReq (xdata, name);
1321 single_p (xdata, &length, 0); /* End Of Message */
1322
1323 e->Req = MAN_EXECUTE;
1324 e->ReqCh = 0;
1325 e->X->PLength = length;
1326 e->X->P = (byte*)xdata;
1327
1328 pC->request_pending = 1;
1329
1330 return (0);
1331 }
1332
1333 return (-1);
1334}
1335
1336static word SuperTraceCreateReadReq (byte* P, const char* path) {
1337 byte var_length;
1338 byte* plen;
1339
1340 var_length = (byte)strlen (path);
1341
1342 *P++ = ESC;
1343 plen = P++;
1344 *P++ = 0x80; /* MAN_IE */
1345 *P++ = 0x00; /* Type */
1346 *P++ = 0x00; /* Attribute */
1347 *P++ = 0x00; /* Status */
1348 *P++ = 0x00; /* Variable Length */
1349 *P++ = var_length;
1350 memcpy (P, path, var_length);
1351 P += var_length;
1352 *plen = var_length + 0x06;
1353
1354 return ((word)(var_length + 0x08));
1355}
1356
1357static void single_p (byte * P, word * PLength, byte Id) {
1358 P[(*PLength)++] = Id;
1359}
1360
1361static void diva_maint_xdi_cb (ENTITY* e) {
1362 diva_strace_context_t* pLib = DIVAS_CONTAINING_RECORD(e,diva_strace_context_t,e);
1363 diva_maint_client_t* pC;
1364 diva_os_spin_lock_magic_t old_irql, old_irql1;
1365
1366
1367 diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb");
1368 diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb");
1369
1370 pC = (diva_maint_client_t*)pLib->hAdapter;
1371
1372 if ((e->complete == 255) || (pC->dma_handle < 0)) {
1373 if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) {
1374 diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error");
1375 }
1376 } else {
1377 /*
1378 Process combined management interface indication
1379 */
1380 if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) {
1381 diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error (DMA mode)");
1382 }
1383 }
1384
1385 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb");
1386
1387
1388 if (pC->request_pending) {
1389 pC->request_pending = 0;
1390 (*(pC->request))(e);
1391 }
1392
1393 diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb");
1394}
1395
1396
1397static void diva_maint_error (void* user_context,
1398 diva_strace_library_interface_t* hLib,
1399 int Adapter,
1400 int error,
1401 const char* file,
1402 int line) {
1403 diva_mnt_internal_dprintf (0, DLI_ERR,
1404 "Trace library error(%d) A(%d) %s %d", error, Adapter, file, line);
1405}
1406
1407static void print_ie (diva_trace_ie_t* ie, char* buffer, int length) {
1408 int i;
1409
1410 buffer[0] = 0;
1411
1412 if (length > 32) {
1413 for (i = 0; ((i < ie->length) && (length > 3)); i++) {
1414 sprintf (buffer, "%02x", ie->data[i]);
1415 buffer += 2;
1416 length -= 2;
1417 if (i < (ie->length-1)) {
1418 strcpy (buffer, " ");
1419 buffer++;
1420 length--;
1421 }
1422 }
1423 }
1424}
1425
1426static void diva_maint_state_change_notify (void* user_context,
1427 diva_strace_library_interface_t* hLib,
1428 int Adapter,
1429 diva_trace_line_state_t* channel,
1430 int notify_subject) {
1431 diva_maint_client_t* pC = (diva_maint_client_t*)user_context;
1432 diva_trace_fax_state_t* fax = &channel->fax;
1433 diva_trace_modem_state_t* modem = &channel->modem;
1434 char tmp[256];
1435
1436 if (!pC->hDbg) {
1437 return;
1438 }
1439
1440 switch (notify_subject) {
1441 case DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE: {
1442 int view = (TraceFilter[0] == 0);
1443 /*
1444 Process selective Trace
1445 */
1446 if (channel->Line[0] == 'I' && channel->Line[1] == 'd' &&
1447 channel->Line[2] == 'l' && channel->Line[3] == 'e') {
1448 if ((TraceFilterIdent == pC->hDbg->id) && (TraceFilterChannel == (int)channel->ChannelNumber)) {
1449 (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 0);
1450 (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 0);
1451 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace OFF for Ch=%d",
1452 (int)channel->ChannelNumber);
1453 TraceFilterIdent = -1;
1454 TraceFilterChannel = -1;
1455 view = 1;
1456 }
1457 } else if (TraceFilter[0] && (TraceFilterIdent < 0) && !(diva_mnt_cmp_nmbr (&channel->RemoteAddress[0]) &&
1458 diva_mnt_cmp_nmbr (&channel->LocalAddress[0]))) {
1459
1460 if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0) { /* Activate B-channel trace */
1461 (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 1);
1462 }
1463 if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0) { /* Activate AudioTap Trace */
1464 (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 1);
1465 }
1466
1467 TraceFilterIdent = pC->hDbg->id;
1468 TraceFilterChannel = (int)channel->ChannelNumber;
1469
1470 if (TraceFilterIdent >= 0) {
1471 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace ON for Ch=%d",
1472 (int)channel->ChannelNumber);
1473 view = 1;
1474 }
1475 }
1476 if (view && (pC->hDbg->dbgMask & DIVA_MGT_DBG_LINE_EVENTS)) {
1477 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Ch = %d",
1478 (int)channel->ChannelNumber);
1479 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Status = <%s>", &channel->Line[0]);
1480 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Layer1 = <%s>", &channel->Framing[0]);
1481 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Layer2 = <%s>", &channel->Layer2[0]);
1482 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Layer3 = <%s>", &channel->Layer3[0]);
1483 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L RAddr = <%s>",
1484 &channel->RemoteAddress[0]);
1485 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L RSAddr = <%s>",
1486 &channel->RemoteSubAddress[0]);
1487 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L LAddr = <%s>",
1488 &channel->LocalAddress[0]);
1489 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L LSAddr = <%s>",
1490 &channel->LocalSubAddress[0]);
1491 print_ie(&channel->call_BC, tmp, sizeof(tmp));
1492 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L BC = <%s>", tmp);
1493 print_ie(&channel->call_HLC, tmp, sizeof(tmp));
1494 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L HLC = <%s>", tmp);
1495 print_ie(&channel->call_LLC, tmp, sizeof(tmp));
1496 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L LLC = <%s>", tmp);
1497 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L CR = 0x%x", channel->CallReference);
1498 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Disc = 0x%x",
1499 channel->LastDisconnecCause);
1500 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Owner = <%s>", &channel->UserID[0]);
1501 }
1502
1503 } break;
1504
1505 case DIVA_SUPER_TRACE_NOTIFY_MODEM_CHANGE:
1506 if (pC->hDbg->dbgMask & DIVA_MGT_DBG_MDM_PROGRESS) {
1507 {
1508 int ch = TraceFilterChannel;
1509 int id = TraceFilterIdent;
1510
1511 if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) &&
1512 (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
1513 if (ch != (int)modem->ChannelNumber) {
1514 break;
1515 }
1516 } else if (TraceFilter[0] != 0) {
1517 break;
1518 }
1519 }
1520
1521
1522 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Ch = %lu",
1523 (int)modem->ChannelNumber);
1524 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Event = %lu", modem->Event);
1525 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Norm = %lu", modem->Norm);
1526 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Opts. = 0x%08x", modem->Options);
1527 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Tx = %lu Bps", modem->TxSpeed);
1528 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Rx = %lu Bps", modem->RxSpeed);
1529 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM RT = %lu mSec",
1530 modem->RoundtripMsec);
1531 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Sr = %lu", modem->SymbolRate);
1532 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Rxl = %d dBm", modem->RxLeveldBm);
1533 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM El = %d dBm", modem->EchoLeveldBm);
1534 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM SNR = %lu dB", modem->SNRdb);
1535 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM MAE = %lu", modem->MAE);
1536 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM LRet = %lu",
1537 modem->LocalRetrains);
1538 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM RRet = %lu",
1539 modem->RemoteRetrains);
1540 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM LRes = %lu", modem->LocalResyncs);
1541 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM RRes = %lu",
1542 modem->RemoteResyncs);
1543 if (modem->Event == 3) {
1544 diva_mnt_internal_dprintf(pC->hDbg->id,DLI_STAT,"MDM Disc = %lu", modem->DiscReason);
1545 }
1546 }
1547 if ((modem->Event == 3) && (pC->hDbg->dbgMask & DIVA_MGT_DBG_MDM_STATISTICS)) {
1548 (*(pC->pIdiLib->DivaSTraceGetModemStatistics))(pC->pIdiLib);
1549 }
1550 break;
1551
1552 case DIVA_SUPER_TRACE_NOTIFY_FAX_CHANGE:
1553 if (pC->hDbg->dbgMask & DIVA_MGT_DBG_FAX_PROGRESS) {
1554 {
1555 int ch = TraceFilterChannel;
1556 int id = TraceFilterIdent;
1557
1558 if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) &&
1559 (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
1560 if (ch != (int)fax->ChannelNumber) {
1561 break;
1562 }
1563 } else if (TraceFilter[0] != 0) {
1564 break;
1565 }
1566 }
1567
1568 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Ch = %lu",(int)fax->ChannelNumber);
1569 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Event = %lu", fax->Event);
1570 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Pages = %lu", fax->Page_Counter);
1571 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Feat. = 0x%08x", fax->Features);
1572 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX ID = <%s>", &fax->Station_ID[0]);
1573 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Saddr = <%s>", &fax->Subaddress[0]);
1574 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Pwd = <%s>", &fax->Password[0]);
1575 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Speed = %lu", fax->Speed);
1576 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Res. = 0x%08x", fax->Resolution);
1577 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Width = %lu", fax->Paper_Width);
1578 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Length= %lu", fax->Paper_Length);
1579 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX SLT = %lu", fax->Scanline_Time);
1580 if (fax->Event == 3) {
1581 diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Disc = %lu", fax->Disc_Reason);
1582 }
1583 }
1584 if ((fax->Event == 3) && (pC->hDbg->dbgMask & DIVA_MGT_DBG_FAX_STATISTICS)) {
1585 (*(pC->pIdiLib->DivaSTraceGetFaxStatistics))(pC->pIdiLib);
1586 }
1587 break;
1588
1589 case DIVA_SUPER_TRACE_INTERFACE_CHANGE:
1590 if (pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_EVENTS) {
1591 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT,
1592 "Layer 1 -> [%s]", channel->pInterface->Layer1);
1593 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT,
1594 "Layer 2 -> [%s]", channel->pInterface->Layer2);
1595 }
1596 break;
1597
1598 case DIVA_SUPER_TRACE_NOTIFY_STAT_CHANGE:
1599 if (pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_STATISTICS) {
1600 /*
1601 Incoming Statistics
1602 */
1603 if (channel->pInterfaceStat->inc.Calls) {
1604 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1605 "Inc Calls =%lu", channel->pInterfaceStat->inc.Calls);
1606 }
1607 if (channel->pInterfaceStat->inc.Connected) {
1608 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1609 "Inc Connected =%lu", channel->pInterfaceStat->inc.Connected);
1610 }
1611 if (channel->pInterfaceStat->inc.User_Busy) {
1612 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1613 "Inc Busy =%lu", channel->pInterfaceStat->inc.User_Busy);
1614 }
1615 if (channel->pInterfaceStat->inc.Call_Rejected) {
1616 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1617 "Inc Rejected =%lu", channel->pInterfaceStat->inc.Call_Rejected);
1618 }
1619 if (channel->pInterfaceStat->inc.Wrong_Number) {
1620 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1621 "Inc Wrong Nr =%lu", channel->pInterfaceStat->inc.Wrong_Number);
1622 }
1623 if (channel->pInterfaceStat->inc.Incompatible_Dst) {
1624 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1625 "Inc Incomp. Dest =%lu", channel->pInterfaceStat->inc.Incompatible_Dst);
1626 }
1627 if (channel->pInterfaceStat->inc.Out_of_Order) {
1628 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1629 "Inc Out of Order =%lu", channel->pInterfaceStat->inc.Out_of_Order);
1630 }
1631 if (channel->pInterfaceStat->inc.Ignored) {
1632 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1633 "Inc Ignored =%lu", channel->pInterfaceStat->inc.Ignored);
1634 }
1635
1636 /*
1637 Outgoing Statistics
1638 */
1639 if (channel->pInterfaceStat->outg.Calls) {
1640 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1641 "Outg Calls =%lu", channel->pInterfaceStat->outg.Calls);
1642 }
1643 if (channel->pInterfaceStat->outg.Connected) {
1644 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1645 "Outg Connected =%lu", channel->pInterfaceStat->outg.Connected);
1646 }
1647 if (channel->pInterfaceStat->outg.User_Busy) {
1648 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1649 "Outg Busy =%lu", channel->pInterfaceStat->outg.User_Busy);
1650 }
1651 if (channel->pInterfaceStat->outg.No_Answer) {
1652 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1653 "Outg No Answer =%lu", channel->pInterfaceStat->outg.No_Answer);
1654 }
1655 if (channel->pInterfaceStat->outg.Wrong_Number) {
1656 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1657 "Outg Wrong Nr =%lu", channel->pInterfaceStat->outg.Wrong_Number);
1658 }
1659 if (channel->pInterfaceStat->outg.Call_Rejected) {
1660 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1661 "Outg Rejected =%lu", channel->pInterfaceStat->outg.Call_Rejected);
1662 }
1663 if (channel->pInterfaceStat->outg.Other_Failures) {
1664 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1665 "Outg Other Failures =%lu", channel->pInterfaceStat->outg.Other_Failures);
1666 }
1667 }
1668 break;
1669
1670 case DIVA_SUPER_TRACE_NOTIFY_MDM_STAT_CHANGE:
1671 if (channel->pInterfaceStat->mdm.Disc_Normal) {
1672 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1673 "MDM Disc Normal = %lu", channel->pInterfaceStat->mdm.Disc_Normal);
1674 }
1675 if (channel->pInterfaceStat->mdm.Disc_Unspecified) {
1676 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1677 "MDM Disc Unsp. = %lu", channel->pInterfaceStat->mdm.Disc_Unspecified);
1678 }
1679 if (channel->pInterfaceStat->mdm.Disc_Busy_Tone) {
1680 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1681 "MDM Disc Busy Tone = %lu", channel->pInterfaceStat->mdm.Disc_Busy_Tone);
1682 }
1683 if (channel->pInterfaceStat->mdm.Disc_Congestion) {
1684 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1685 "MDM Disc Congestion = %lu", channel->pInterfaceStat->mdm.Disc_Congestion);
1686 }
1687 if (channel->pInterfaceStat->mdm.Disc_Carr_Wait) {
1688 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1689 "MDM Disc Carrier Wait = %lu", channel->pInterfaceStat->mdm.Disc_Carr_Wait);
1690 }
1691 if (channel->pInterfaceStat->mdm.Disc_Trn_Timeout) {
1692 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1693 "MDM Disc Trn. T.o. = %lu", channel->pInterfaceStat->mdm.Disc_Trn_Timeout);
1694 }
1695 if (channel->pInterfaceStat->mdm.Disc_Incompat) {
1696 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1697 "MDM Disc Incompatible = %lu", channel->pInterfaceStat->mdm.Disc_Incompat);
1698 }
1699 if (channel->pInterfaceStat->mdm.Disc_Frame_Rej) {
1700 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1701 "MDM Disc Frame Reject = %lu", channel->pInterfaceStat->mdm.Disc_Frame_Rej);
1702 }
1703 if (channel->pInterfaceStat->mdm.Disc_V42bis) {
1704 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1705 "MDM Disc V.42bis = %lu", channel->pInterfaceStat->mdm.Disc_V42bis);
1706 }
1707 break;
1708
1709 case DIVA_SUPER_TRACE_NOTIFY_FAX_STAT_CHANGE:
1710 if (channel->pInterfaceStat->fax.Disc_Normal) {
1711 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1712 "FAX Disc Normal = %lu", channel->pInterfaceStat->fax.Disc_Normal);
1713 }
1714 if (channel->pInterfaceStat->fax.Disc_Not_Ident) {
1715 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1716 "FAX Disc Not Ident. = %lu", channel->pInterfaceStat->fax.Disc_Not_Ident);
1717 }
1718 if (channel->pInterfaceStat->fax.Disc_No_Response) {
1719 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1720 "FAX Disc No Response = %lu", channel->pInterfaceStat->fax.Disc_No_Response);
1721 }
1722 if (channel->pInterfaceStat->fax.Disc_Retries) {
1723 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1724 "FAX Disc Max Retries = %lu", channel->pInterfaceStat->fax.Disc_Retries);
1725 }
1726 if (channel->pInterfaceStat->fax.Disc_Unexp_Msg) {
1727 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1728 "FAX Unexp. Msg. = %lu", channel->pInterfaceStat->fax.Disc_Unexp_Msg);
1729 }
1730 if (channel->pInterfaceStat->fax.Disc_No_Polling) {
1731 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1732 "FAX Disc No Polling = %lu", channel->pInterfaceStat->fax.Disc_No_Polling);
1733 }
1734 if (channel->pInterfaceStat->fax.Disc_Training) {
1735 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1736 "FAX Disc Training = %lu", channel->pInterfaceStat->fax.Disc_Training);
1737 }
1738 if (channel->pInterfaceStat->fax.Disc_Unexpected) {
1739 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1740 "FAX Disc Unexpected = %lu", channel->pInterfaceStat->fax.Disc_Unexpected);
1741 }
1742 if (channel->pInterfaceStat->fax.Disc_Application) {
1743 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1744 "FAX Disc Application = %lu", channel->pInterfaceStat->fax.Disc_Application);
1745 }
1746 if (channel->pInterfaceStat->fax.Disc_Incompat) {
1747 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1748 "FAX Disc Incompatible = %lu", channel->pInterfaceStat->fax.Disc_Incompat);
1749 }
1750 if (channel->pInterfaceStat->fax.Disc_No_Command) {
1751 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1752 "FAX Disc No Command = %lu", channel->pInterfaceStat->fax.Disc_No_Command);
1753 }
1754 if (channel->pInterfaceStat->fax.Disc_Long_Msg) {
1755 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1756 "FAX Disc Long Msg. = %lu", channel->pInterfaceStat->fax.Disc_Long_Msg);
1757 }
1758 if (channel->pInterfaceStat->fax.Disc_Supervisor) {
1759 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1760 "FAX Disc Supervisor = %lu", channel->pInterfaceStat->fax.Disc_Supervisor);
1761 }
1762 if (channel->pInterfaceStat->fax.Disc_SUB_SEP_PWD) {
1763 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1764 "FAX Disc SUP SEP PWD = %lu", channel->pInterfaceStat->fax.Disc_SUB_SEP_PWD);
1765 }
1766 if (channel->pInterfaceStat->fax.Disc_Invalid_Msg) {
1767 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1768 "FAX Disc Invalid Msg. = %lu", channel->pInterfaceStat->fax.Disc_Invalid_Msg);
1769 }
1770 if (channel->pInterfaceStat->fax.Disc_Page_Coding) {
1771 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1772 "FAX Disc Page Coding = %lu", channel->pInterfaceStat->fax.Disc_Page_Coding);
1773 }
1774 if (channel->pInterfaceStat->fax.Disc_App_Timeout) {
1775 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1776 "FAX Disc Appl. T.o. = %lu", channel->pInterfaceStat->fax.Disc_App_Timeout);
1777 }
1778 if (channel->pInterfaceStat->fax.Disc_Unspecified) {
1779 diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1780 "FAX Disc Unspec. = %lu", channel->pInterfaceStat->fax.Disc_Unspecified);
1781 }
1782 break;
1783 }
1784}
1785
1786/*
1787 Receive trace information from the Management Interface and store it in the
1788 internal trace buffer with MSG_TYPE_MLOG as is, without any filtering.
1789 Event Filtering and formatting is done in Management Interface self.
1790 */
1791static void diva_maint_trace_notify (void* user_context,
1792 diva_strace_library_interface_t* hLib,
1793 int Adapter,
1794 void* xlog_buffer,
1795 int length) {
1796 diva_maint_client_t* pC = (diva_maint_client_t*)user_context;
1797 diva_dbg_entry_head_t* pmsg;
1798 word size;
1799 dword sec, usec;
1800 int ch = TraceFilterChannel;
1801 int id = TraceFilterIdent;
1802
1803 /*
1804 Selective trace
1805 */
1806 if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) &&
1807 (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
1808 const char* p = NULL;
1809 int ch_value = -1;
1810 MI_XLOG_HDR *TrcData = (MI_XLOG_HDR *)xlog_buffer;
1811
1812 if (Adapter != clients[id].logical) {
1813 return; /* Ignore all trace messages from other adapters */
1814 }
1815
1816 if (TrcData->code == 24) {
1817 p = (char*)&TrcData->code;
1818 p += 2;
1819 }
1820
1821 /*
1822 All L1 messages start as [dsp,ch], so we can filter this information
1823 and filter out all messages that use different channel
1824 */
1825 if (p && p[0] == '[') {
1826 if (p[2] == ',') {
1827 p += 3;
1828 ch_value = *p - '0';
1829 } else if (p[3] == ',') {
1830 p += 4;
1831 ch_value = *p - '0';
1832 }
1833 if (ch_value >= 0) {
1834 if (p[2] == ']') {
1835 ch_value = ch_value * 10 + p[1] - '0';
1836 }
1837 if (ch_value != ch) {
1838 return; /* Ignore other channels */
1839 }
1840 }
1841 }
1842
1843 } else if (TraceFilter[0] != 0) {
1844 return; /* Ignore trace if trace filter is activated, but idle */
1845 }
1846
1847 diva_os_get_time (&sec, &usec);
1848
1849 while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue,
1850 (word)length+sizeof(*pmsg)))) {
1851 if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) {
1852 queueFreeMsg (dbg_queue);
1853 } else {
1854 break;
1855 }
1856 }
1857 if (pmsg) {
1858 memcpy (&pmsg[1], xlog_buffer, length);
1859 pmsg->sequence = dbg_sequence++;
1860 pmsg->time_sec = sec;
1861 pmsg->time_usec = usec;
1862 pmsg->facility = MSG_TYPE_MLOG;
1863 pmsg->dli = pC->logical;
1864 pmsg->drv_id = pC->hDbg->id;
1865 pmsg->di_cpu = 0;
1866 pmsg->data_length = length;
1867 queueCompleteMsg (pmsg);
1868 if (queueCount(dbg_queue)) {
1869 diva_maint_wakeup_read();
1870 }
1871 }
1872}
1873
1874
1875/*
1876 Convert MAINT trace mask to management interface trace mask/work/facility and
1877 issue command to management interface
1878 */
1879static void diva_change_management_debug_mask (diva_maint_client_t* pC, dword old_mask) {
1880 if (pC->request && pC->hDbg && pC->pIdiLib) {
1881 dword changed = pC->hDbg->dbgMask ^ old_mask;
1882
1883 if (changed & DIVA_MGT_DBG_TRACE) {
1884 (*(pC->pIdiLib->DivaSTraceSetInfo))(pC->pIdiLib,
1885 (pC->hDbg->dbgMask & DIVA_MGT_DBG_TRACE) != 0);
1886 }
1887 if (changed & DIVA_MGT_DBG_DCHAN) {
1888 (*(pC->pIdiLib->DivaSTraceSetDChannel))(pC->pIdiLib,
1889 (pC->hDbg->dbgMask & DIVA_MGT_DBG_DCHAN) != 0);
1890 }
1891 if (!TraceFilter[0]) {
1892 if (changed & DIVA_MGT_DBG_IFC_BCHANNEL) {
1893 int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0);
1894
1895 for (i = 0; i < pC->channels; i++) {
1896 (*(pC->pIdiLib->DivaSTraceSetBChannel))(pC->pIdiLib, i+1, state);
1897 }
1898 }
1899 if (changed & DIVA_MGT_DBG_IFC_AUDIO) {
1900 int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0);
1901
1902 for (i = 0; i < pC->channels; i++) {
1903 (*(pC->pIdiLib->DivaSTraceSetAudioTap))(pC->pIdiLib, i+1, state);
1904 }
1905 }
1906 }
1907 }
1908}
1909
1910
1911void diva_mnt_internal_dprintf (dword drv_id, dword type, char* fmt, ...) {
1912 va_list ap;
1913
1914 va_start(ap, fmt);
1915 DI_format (0, (word)drv_id, (int)type, fmt, ap);
1916 va_end(ap);
1917}
1918
1919/*
1920 Shutdown all adapters before driver removal
1921 */
1922int diva_mnt_shutdown_xdi_adapters (void) {
1923 diva_os_spin_lock_magic_t old_irql, old_irql1;
1924 int i, fret = 0;
1925 byte * pmem;
1926
1927
1928 for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
1929 pmem = NULL;
1930
1931 diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "unload");
1932 diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "unload");
1933
1934 if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) {
1935 if ((*(clients[i].pIdiLib->DivaSTraceLibraryStop))(clients[i].pIdiLib) == 1) {
1936 /*
1937 Adapter removal complete
1938 */
1939 if (clients[i].pIdiLib) {
1940 (*(clients[i].pIdiLib->DivaSTraceLibraryFinit))(clients[i].pIdiLib->hLib);
1941 clients[i].pIdiLib = NULL;
1942
1943 pmem = clients[i].pmem;
1944 clients[i].pmem = NULL;
1945 }
1946 clients[i].hDbg = NULL;
1947 clients[i].request_pending = 0;
1948
1949 if (clients[i].dma_handle >= 0) {
1950 /*
1951 Free DMA handle
1952 */
1953 diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle);
1954 clients[i].dma_handle = -1;
1955 }
1956 clients[i].request = NULL;
1957 } else {
1958 fret = -1;
1959 }
1960 }
1961
1962 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "unload");
1963 if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) {
1964 clients[i].request_pending = 0;
1965 (*(clients[i].request))((ENTITY*)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib));
1966 if (clients[i].dma_handle >= 0) {
1967 diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle);
1968 clients[i].dma_handle = -1;
1969 }
1970 }
1971 diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "unload");
1972
1973 if (pmem) {
1974 diva_os_free (0, pmem);
1975 }
1976 }
1977
1978 return (fret);
1979}
1980
1981/*
1982 Set/Read the trace filter used for selective tracing.
1983 Affects B- and Audio Tap trace mask at run time
1984 */
1985int diva_set_trace_filter (int filter_length, const char* filter) {
1986 diva_os_spin_lock_magic_t old_irql, old_irql1;
1987 int i, ch, on, client_b_on, client_atap_on;
1988
1989 diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
1990 diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
1991
1992 if (filter_length <= DIVA_MAX_SELECTIVE_FILTER_LENGTH) {
1993 memcpy (&TraceFilter[0], filter, filter_length);
1994 if (TraceFilter[filter_length]) {
1995 TraceFilter[filter_length] = 0;
1996 }
1997 if (TraceFilter[0] == '*') {
1998 TraceFilter[0] = 0;
1999 }
2000 } else {
2001 filter_length = -1;
2002 }
2003
2004 TraceFilterIdent = -1;
2005 TraceFilterChannel = -1;
2006
2007 on = (TraceFilter[0] == 0);
2008
2009 for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
2010 if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) {
2011 client_b_on = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0);
2012 client_atap_on = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0);
2013 for (ch = 0; ch < clients[i].channels; ch++) {
2014 (*(clients[i].pIdiLib->DivaSTraceSetBChannel))(clients[i].pIdiLib->hLib, ch+1, client_b_on);
2015 (*(clients[i].pIdiLib->DivaSTraceSetAudioTap))(clients[i].pIdiLib->hLib, ch+1, client_atap_on);
2016 }
2017 }
2018 }
2019
2020 for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
2021 if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) {
2022 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
2023 clients[i].request_pending = 0;
2024 (*(clients[i].request))((ENTITY*)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib));
2025 diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
2026 }
2027 }
2028
2029 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
2030 diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
2031
2032 return (filter_length);
2033}
2034
2035int diva_get_trace_filter (int max_length, char* filter) {
2036 diva_os_spin_lock_magic_t old_irql;
2037 int len;
2038
2039 diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read_filter");
2040 len = strlen (&TraceFilter[0]) + 1;
2041 if (max_length >= len) {
2042 memcpy (filter, &TraceFilter[0], len);
2043 }
2044 diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_filter");
2045
2046 return (len);
2047}
2048
2049static int diva_dbg_cmp_key (const char* ref, const char* key) {
2050 while (*key && (*ref++ == *key++));
2051 return (!*key && !*ref);
2052}
2053
2054/*
2055 In case trace filter starts with "C" character then
2056 all following characters are interpreted as command.
2057 Followings commands are available:
2058 - single, trace single call at time, independent from CPN/CiPN
2059 */
2060static int diva_mnt_cmp_nmbr (const char* nmbr) {
2061 const char* ref = &TraceFilter[0];
2062 int ref_len = strlen(&TraceFilter[0]), nmbr_len = strlen(nmbr);
2063
2064 if (ref[0] == 'C') {
2065 if (diva_dbg_cmp_key (&ref[1], "single")) {
2066 return (0);
2067 }
2068 return (-1);
2069 }
2070
2071 if (!ref_len || (ref_len > nmbr_len)) {
2072 return (-1);
2073 }
2074
2075 nmbr = nmbr + nmbr_len - 1;
2076 ref = ref + ref_len - 1;
2077
2078 while (ref_len--) {
2079 if (*nmbr-- != *ref--) {
2080 return (-1);
2081 }
2082 }
2083
2084 return (0);
2085}
2086
2087static int diva_get_dma_descriptor (IDI_CALL request, dword *dma_magic) {
2088 ENTITY e;
2089 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
2090
2091 if (!request) {
2092 return (-1);
2093 }
2094
2095 pReq->xdi_dma_descriptor_operation.Req = 0;
2096 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
2097
2098 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
2099 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
2100 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
2101 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
2102
2103 (*request)((ENTITY*)pReq);
2104
2105 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
2106 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
2107 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
2108 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
2109 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
2110 } else {
2111 return (-1);
2112 }
2113}
2114
2115static void diva_free_dma_descriptor (IDI_CALL request, int nr) {
2116 ENTITY e;
2117 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
2118
2119 if (!request || (nr < 0)) {
2120 return;
2121 }
2122
2123 pReq->xdi_dma_descriptor_operation.Req = 0;
2124 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
2125
2126 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
2127 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
2128 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
2129 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
2130
2131 (*request)((ENTITY*)pReq);
2132}
2133
diff --git a/drivers/isdn/hardware/eicon/debug_if.h b/drivers/isdn/hardware/eicon/debug_if.h
new file mode 100644
index 000000000000..4db739d5803c
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/debug_if.h
@@ -0,0 +1,90 @@
1/*
2 *
3 Copyright (c) Eicon Technology Corporation, 2000.
4 *
5 This source file is supplied for the use with Eicon
6 Technology Corporation's range of DIVA Server Adapters.
7 *
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12 *
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
15 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 See the GNU General Public License for more details.
17 *
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 */
23#ifndef __DIVA_DEBUG_IF_H__
24#define __DIVA_DEBUG_IF_H__
25#define MSG_TYPE_DRV_ID 0x0001
26#define MSG_TYPE_FLAGS 0x0002
27#define MSG_TYPE_STRING 0x0003
28#define MSG_TYPE_BINARY 0x0004
29#define MSG_TYPE_MLOG 0x0005
30
31#define MSG_FRAME_MAX_SIZE 2150
32
33typedef struct _diva_dbg_entry_head {
34 dword sequence;
35 dword time_sec;
36 dword time_usec;
37 dword facility;
38 dword dli;
39 dword drv_id;
40 dword di_cpu;
41 dword data_length;
42} diva_dbg_entry_head_t;
43
44int diva_maint_init (byte* base, unsigned long length, int do_init);
45void* diva_maint_finit (void);
46dword diva_dbg_q_length (void);
47diva_dbg_entry_head_t* diva_maint_get_message (word* size,
48 diva_os_spin_lock_magic_t* old_irql);
49void diva_maint_ack_message (int do_release,
50 diva_os_spin_lock_magic_t* old_irql);
51void diva_maint_prtComp (char *format, ...);
52void diva_maint_wakeup_read (void);
53int diva_get_driver_info (dword id, byte* data, int data_length);
54int diva_get_driver_dbg_mask (dword id, byte* data);
55int diva_set_driver_dbg_mask (dword id, dword mask);
56void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d);
57void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d);
58int diva_mnt_shutdown_xdi_adapters (void);
59
60#define DIVA_MAX_SELECTIVE_FILTER_LENGTH 127
61int diva_set_trace_filter (int filter_length, const char* filter);
62int diva_get_trace_filter (int max_length, char* filter);
63
64
65#define DITRACE_CMD_GET_DRIVER_INFO 1
66#define DITRACE_READ_DRIVER_DBG_MASK 2
67#define DITRACE_WRITE_DRIVER_DBG_MASK 3
68#define DITRACE_READ_TRACE_ENTRY 4
69#define DITRACE_READ_TRACE_ENTRYS 5
70#define DITRACE_WRITE_SELECTIVE_TRACE_FILTER 6
71#define DITRACE_READ_SELECTIVE_TRACE_FILTER 7
72
73/*
74 Trace lavels for debug via management interface
75 */
76#define DIVA_MGT_DBG_TRACE 0x00000001 /* All trace messages from the card */
77#define DIVA_MGT_DBG_DCHAN 0x00000002 /* All D-channel relater trace messages */
78#define DIVA_MGT_DBG_MDM_PROGRESS 0x00000004 /* Modem progress events */
79#define DIVA_MGT_DBG_FAX_PROGRESS 0x00000008 /* Fax progress events */
80#define DIVA_MGT_DBG_IFC_STATISTICS 0x00000010 /* Interface call statistics */
81#define DIVA_MGT_DBG_MDM_STATISTICS 0x00000020 /* Global modem statistics */
82#define DIVA_MGT_DBG_FAX_STATISTICS 0x00000040 /* Global call statistics */
83#define DIVA_MGT_DBG_LINE_EVENTS 0x00000080 /* Line state events */
84#define DIVA_MGT_DBG_IFC_EVENTS 0x00000100 /* Interface/L1/L2 state events */
85#define DIVA_MGT_DBG_IFC_BCHANNEL 0x00000200 /* B-Channel trace for all channels */
86#define DIVA_MGT_DBG_IFC_AUDIO 0x00000400 /* Audio Tap trace for all channels */
87
88# endif /* DEBUG_IF___H */
89
90
diff --git a/drivers/isdn/hardware/eicon/debuglib.c b/drivers/isdn/hardware/eicon/debuglib.c
new file mode 100644
index 000000000000..a19b7ffe9ace
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/debuglib.c
@@ -0,0 +1,156 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26
27#include "debuglib.h"
28
29#ifdef DIVA_NO_DEBUGLIB
30static DIVA_DI_PRINTF dprintf;
31#else /* DIVA_NO_DEBUGLIB */
32
33_DbgHandle_ myDriverDebugHandle = { 0 /*!Registered*/, DBG_HANDLE_VERSION };
34DIVA_DI_PRINTF dprintf = no_printf;
35/*****************************************************************************/
36#define DBG_FUNC(name) \
37void \
38myDbgPrint_##name (char *format, ...) \
39{ va_list ap ; \
40 if ( myDriverDebugHandle.dbg_prt ) \
41 { va_start (ap, format) ; \
42 (myDriverDebugHandle.dbg_prt) \
43 (myDriverDebugHandle.id, DLI_##name, format, ap) ; \
44 va_end (ap) ; \
45} }
46DBG_FUNC(LOG)
47DBG_FUNC(FTL)
48DBG_FUNC(ERR)
49DBG_FUNC(TRC)
50DBG_FUNC(MXLOG)
51DBG_FUNC(FTL_MXLOG)
52void
53myDbgPrint_EVL (long msgID, ...)
54{ va_list ap ;
55 if ( myDriverDebugHandle.dbg_ev )
56 { va_start (ap, msgID) ;
57 (myDriverDebugHandle.dbg_ev)
58 (myDriverDebugHandle.id, (unsigned long)msgID, ap) ;
59 va_end (ap) ;
60} }
61DBG_FUNC(REG)
62DBG_FUNC(MEM)
63DBG_FUNC(SPL)
64DBG_FUNC(IRP)
65DBG_FUNC(TIM)
66DBG_FUNC(BLK)
67DBG_FUNC(TAPI)
68DBG_FUNC(NDIS)
69DBG_FUNC(CONN)
70DBG_FUNC(STAT)
71DBG_FUNC(SEND)
72DBG_FUNC(RECV)
73DBG_FUNC(PRV0)
74DBG_FUNC(PRV1)
75DBG_FUNC(PRV2)
76DBG_FUNC(PRV3)
77/*****************************************************************************/
78int
79DbgRegister (char *drvName, char *drvTag, unsigned long dbgMask)
80{
81 int len;
82/*
83 * deregister (if already registered) and zero out myDriverDebugHandle
84 */
85 DbgDeregister () ;
86/*
87 * initialize the debug handle
88 */
89 myDriverDebugHandle.Version = DBG_HANDLE_VERSION ;
90 myDriverDebugHandle.id = -1 ;
91 myDriverDebugHandle.dbgMask = dbgMask | (DL_EVL | DL_FTL | DL_LOG) ;
92 len = strlen (drvName) ;
93 memcpy (myDriverDebugHandle.drvName, drvName,
94 (len < sizeof(myDriverDebugHandle.drvName)) ?
95 len : sizeof(myDriverDebugHandle.drvName) - 1) ;
96 len = strlen (drvTag) ;
97 memcpy (myDriverDebugHandle.drvTag, drvTag,
98 (len < sizeof(myDriverDebugHandle.drvTag)) ?
99 len : sizeof(myDriverDebugHandle.drvTag) - 1) ;
100/*
101 * Try to register debugging via old (and only) interface
102 */
103 dprintf("\000\377", &myDriverDebugHandle) ;
104 if ( myDriverDebugHandle.dbg_prt )
105 {
106 return (1) ;
107 }
108/*
109 * Check if we registered whith an old maint driver (see debuglib.h)
110 */
111 if ( myDriverDebugHandle.dbg_end != NULL
112 /* location of 'dbg_prt' in _OldDbgHandle_ struct */
113 && (myDriverDebugHandle.regTime.LowPart ||
114 myDriverDebugHandle.regTime.HighPart ) )
115 /* same location as in _OldDbgHandle_ struct */
116 {
117 dprintf("%s: Cannot log to old maint driver !", drvName) ;
118 myDriverDebugHandle.dbg_end =
119 ((_OldDbgHandle_ *)&myDriverDebugHandle)->dbg_end ;
120 DbgDeregister () ;
121 }
122 return (0) ;
123}
124/*****************************************************************************/
125void
126DbgSetLevel (unsigned long dbgMask)
127{
128 myDriverDebugHandle.dbgMask = dbgMask | (DL_EVL | DL_FTL | DL_LOG) ;
129}
130/*****************************************************************************/
131void
132DbgDeregister (void)
133{
134 if ( myDriverDebugHandle.dbg_end )
135 {
136 (myDriverDebugHandle.dbg_end)(&myDriverDebugHandle) ;
137 }
138 memset (&myDriverDebugHandle, 0, sizeof(myDriverDebugHandle)) ;
139}
140void xdi_dbg_xlog (char* x, ...) {
141 va_list ap;
142 va_start (ap, x);
143 if (myDriverDebugHandle.dbg_end &&
144 (myDriverDebugHandle.dbg_irq || myDriverDebugHandle.dbg_old) &&
145 (myDriverDebugHandle.dbgMask & DL_STAT)) {
146 if (myDriverDebugHandle.dbg_irq) {
147 (*(myDriverDebugHandle.dbg_irq))(myDriverDebugHandle.id,
148 (x[0] != 0) ? DLI_TRC : DLI_XLOG, x, ap);
149 } else {
150 (*(myDriverDebugHandle.dbg_old))(myDriverDebugHandle.id, x, ap);
151 }
152 }
153 va_end(ap);
154}
155/*****************************************************************************/
156#endif /* DIVA_NO_DEBUGLIB */
diff --git a/drivers/isdn/hardware/eicon/debuglib.h b/drivers/isdn/hardware/eicon/debuglib.h
new file mode 100644
index 000000000000..11b3b9edd1d6
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/debuglib.h
@@ -0,0 +1,322 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#if !defined(__DEBUGLIB_H__)
27#define __DEBUGLIB_H__
28#include <stdarg.h>
29/*
30 * define global debug priorities
31 */
32#define DL_LOG 0x00000001 /* always worth mentioning */
33#define DL_FTL 0x00000002 /* always sampled error */
34#define DL_ERR 0x00000004 /* any kind of error */
35#define DL_TRC 0x00000008 /* verbose information */
36#define DL_XLOG 0x00000010 /* old xlog info */
37#define DL_MXLOG 0x00000020 /* maestra xlog info */
38#define DL_FTL_MXLOG 0x00000021 /* fatal maestra xlog info */
39#define DL_EVL 0x00000080 /* special NT eventlog msg */
40#define DL_COMPAT (DL_MXLOG | DL_XLOG)
41#define DL_PRIOR_MASK (DL_EVL | DL_COMPAT | DL_TRC | DL_ERR | DL_FTL | DL_LOG)
42#define DLI_LOG 0x0100
43#define DLI_FTL 0x0200
44#define DLI_ERR 0x0300
45#define DLI_TRC 0x0400
46#define DLI_XLOG 0x0500
47#define DLI_MXLOG 0x0600
48#define DLI_FTL_MXLOG 0x0600
49#define DLI_EVL 0x0800
50/*
51 * define OS (operating system interface) debuglevel
52 */
53#define DL_REG 0x00000100 /* init/query registry */
54#define DL_MEM 0x00000200 /* memory management */
55#define DL_SPL 0x00000400 /* event/spinlock handling */
56#define DL_IRP 0x00000800 /* I/O request handling */
57#define DL_TIM 0x00001000 /* timer/watchdog handling */
58#define DL_BLK 0x00002000 /* raw data block contents */
59#define DL_OS_MASK (DL_BLK | DL_TIM | DL_IRP | DL_SPL | DL_MEM | DL_REG)
60#define DLI_REG 0x0900
61#define DLI_MEM 0x0A00
62#define DLI_SPL 0x0B00
63#define DLI_IRP 0x0C00
64#define DLI_TIM 0x0D00
65#define DLI_BLK 0x0E00
66/*
67 * define ISDN (connection interface) debuglevel
68 */
69#define DL_TAPI 0x00010000 /* debug TAPI interface */
70#define DL_NDIS 0x00020000 /* debug NDIS interface */
71#define DL_CONN 0x00040000 /* connection handling */
72#define DL_STAT 0x00080000 /* trace state machines */
73#define DL_SEND 0x00100000 /* trace raw xmitted data */
74#define DL_RECV 0x00200000 /* trace raw received data */
75#define DL_DATA (DL_SEND | DL_RECV)
76#define DL_ISDN_MASK (DL_DATA | DL_STAT | DL_CONN | DL_NDIS | DL_TAPI)
77#define DLI_TAPI 0x1100
78#define DLI_NDIS 0x1200
79#define DLI_CONN 0x1300
80#define DLI_STAT 0x1400
81#define DLI_SEND 0x1500
82#define DLI_RECV 0x1600
83/*
84 * define some private (unspecified) debuglevel
85 */
86#define DL_PRV0 0x01000000
87#define DL_PRV1 0x02000000
88#define DL_PRV2 0x04000000
89#define DL_PRV3 0x08000000
90#define DL_PRIV_MASK (DL_PRV0 | DL_PRV1 | DL_PRV2 | DL_PRV3)
91#define DLI_PRV0 0x1900
92#define DLI_PRV1 0x1A00
93#define DLI_PRV2 0x1B00
94#define DLI_PRV3 0x1C00
95#define DT_INDEX(x) ((x) & 0x000F)
96#define DL_INDEX(x) ((((x) >> 8) & 0x00FF) - 1)
97#define DLI_NAME(x) ((x) & 0xFF00)
98/*
99 * Debug mask for kernel mode tracing, if set the output is also sent to
100 * the system debug function. Requires that the project is compiled
101 * with _KERNEL_DBG_PRINT_
102 */
103#define DL_TO_KERNEL 0x40000000
104
105#ifdef DIVA_NO_DEBUGLIB
106#define myDbgPrint_LOG(x...) do { } while(0);
107#define myDbgPrint_FTL(x...) do { } while(0);
108#define myDbgPrint_ERR(x...) do { } while(0);
109#define myDbgPrint_TRC(x...) do { } while(0);
110#define myDbgPrint_MXLOG(x...) do { } while(0);
111#define myDbgPrint_EVL(x...) do { } while(0);
112#define myDbgPrint_REG(x...) do { } while(0);
113#define myDbgPrint_MEM(x...) do { } while(0);
114#define myDbgPrint_SPL(x...) do { } while(0);
115#define myDbgPrint_IRP(x...) do { } while(0);
116#define myDbgPrint_TIM(x...) do { } while(0);
117#define myDbgPrint_BLK(x...) do { } while(0);
118#define myDbgPrint_TAPI(x...) do { } while(0);
119#define myDbgPrint_NDIS(x...) do { } while(0);
120#define myDbgPrint_CONN(x...) do { } while(0);
121#define myDbgPrint_STAT(x...) do { } while(0);
122#define myDbgPrint_SEND(x...) do { } while(0);
123#define myDbgPrint_RECV(x...) do { } while(0);
124#define myDbgPrint_PRV0(x...) do { } while(0);
125#define myDbgPrint_PRV1(x...) do { } while(0);
126#define myDbgPrint_PRV2(x...) do { } while(0);
127#define myDbgPrint_PRV3(x...) do { } while(0);
128#define DBG_TEST(func,args) do { } while(0);
129#define DBG_EVL_ID(args) do { } while(0);
130
131#else /* DIVA_NO_DEBUGLIB */
132/*
133 * define low level macros for formatted & raw debugging
134 */
135#define DBG_DECL(func) extern void myDbgPrint_##func (char *, ...) ;
136DBG_DECL(LOG)
137DBG_DECL(FTL)
138DBG_DECL(ERR)
139DBG_DECL(TRC)
140DBG_DECL(MXLOG)
141DBG_DECL(FTL_MXLOG)
142extern void myDbgPrint_EVL (long, ...) ;
143DBG_DECL(REG)
144DBG_DECL(MEM)
145DBG_DECL(SPL)
146DBG_DECL(IRP)
147DBG_DECL(TIM)
148DBG_DECL(BLK)
149DBG_DECL(TAPI)
150DBG_DECL(NDIS)
151DBG_DECL(CONN)
152DBG_DECL(STAT)
153DBG_DECL(SEND)
154DBG_DECL(RECV)
155DBG_DECL(PRV0)
156DBG_DECL(PRV1)
157DBG_DECL(PRV2)
158DBG_DECL(PRV3)
159#ifdef _KERNEL_DBG_PRINT_
160/*
161 * tracing to maint and kernel if selected in the trace mask.
162 */
163#define DBG_TEST(func,args) \
164{ if ( (myDriverDebugHandle.dbgMask) & (unsigned long)DL_##func ) \
165 { \
166 if ( (myDriverDebugHandle.dbgMask) & DL_TO_KERNEL ) \
167 {DbgPrint args; DbgPrint ("\r\n");} \
168 myDbgPrint_##func args ; \
169} }
170#else
171/*
172 * Standard tracing to maint driver.
173 */
174#define DBG_TEST(func,args) \
175{ if ( (myDriverDebugHandle.dbgMask) & (unsigned long)DL_##func ) \
176 { myDbgPrint_##func args ; \
177} }
178#endif
179/*
180 * For event level debug use a separate define, the paramete are
181 * different and cause compiler errors on some systems.
182 */
183#define DBG_EVL_ID(args) \
184{ if ( (myDriverDebugHandle.dbgMask) & (unsigned long)DL_EVL ) \
185 { myDbgPrint_EVL args ; \
186} }
187
188#endif /* DIVA_NO_DEBUGLIB */
189
190#define DBG_LOG(args) DBG_TEST(LOG, args)
191#define DBG_FTL(args) DBG_TEST(FTL, args)
192#define DBG_ERR(args) DBG_TEST(ERR, args)
193#define DBG_TRC(args) DBG_TEST(TRC, args)
194#define DBG_MXLOG(args) DBG_TEST(MXLOG, args)
195#define DBG_FTL_MXLOG(args) DBG_TEST(FTL_MXLOG, args)
196#define DBG_EVL(args) DBG_EVL_ID(args)
197#define DBG_REG(args) DBG_TEST(REG, args)
198#define DBG_MEM(args) DBG_TEST(MEM, args)
199#define DBG_SPL(args) DBG_TEST(SPL, args)
200#define DBG_IRP(args) DBG_TEST(IRP, args)
201#define DBG_TIM(args) DBG_TEST(TIM, args)
202#define DBG_BLK(args) DBG_TEST(BLK, args)
203#define DBG_TAPI(args) DBG_TEST(TAPI, args)
204#define DBG_NDIS(args) DBG_TEST(NDIS, args)
205#define DBG_CONN(args) DBG_TEST(CONN, args)
206#define DBG_STAT(args) DBG_TEST(STAT, args)
207#define DBG_SEND(args) DBG_TEST(SEND, args)
208#define DBG_RECV(args) DBG_TEST(RECV, args)
209#define DBG_PRV0(args) DBG_TEST(PRV0, args)
210#define DBG_PRV1(args) DBG_TEST(PRV1, args)
211#define DBG_PRV2(args) DBG_TEST(PRV2, args)
212#define DBG_PRV3(args) DBG_TEST(PRV3, args)
213/*
214 * prototypes for debug register/deregister functions in "debuglib.c"
215 */
216#ifdef DIVA_NO_DEBUGLIB
217#define DbgRegister(name,tag, mask) do { } while(0)
218#define DbgDeregister() do { } while(0)
219#define DbgSetLevel(mask) do { } while(0)
220#else
221extern DIVA_DI_PRINTF dprintf;
222extern int DbgRegister (char *drvName, char *drvTag, unsigned long dbgMask) ;
223extern void DbgDeregister (void) ;
224extern void DbgSetLevel (unsigned long dbgMask) ;
225#endif
226/*
227 * driver internal structure for debug handling;
228 * in client drivers this structure is maintained in "debuglib.c",
229 * in the debug driver "debug.c" maintains a chain of such structs.
230 */
231typedef struct _DbgHandle_ *pDbgHandle ;
232typedef void ( * DbgEnd) (pDbgHandle) ;
233typedef void ( * DbgLog) (unsigned short, int, char *, va_list) ;
234typedef void ( * DbgOld) (unsigned short, char *, va_list) ;
235typedef void ( * DbgEv) (unsigned short, unsigned long, va_list) ;
236typedef void ( * DbgIrq) (unsigned short, int, char *, va_list) ;
237typedef struct _DbgHandle_
238{ char Registered ; /* driver successfull registered */
239#define DBG_HANDLE_REG_NEW 0x01 /* this (new) structure */
240#define DBG_HANDLE_REG_OLD 0x7f /* old structure (see below) */
241 char Version; /* version of this structure */
242#define DBG_HANDLE_VERSION 1 /* contains dbg_old function now */
243#define DBG_HANDLE_VER_EXT 2 /* pReserved points to extended info*/
244 short id ; /* internal id of registered driver */
245 struct _DbgHandle_ *next ; /* ptr to next registered driver */
246 struct /*LARGE_INTEGER*/ {
247 unsigned long LowPart;
248 long HighPart;
249 } regTime ; /* timestamp for registration */
250 void *pIrp ; /* ptr to pending i/o request */
251 unsigned long dbgMask ; /* current debug mask */
252 char drvName[16] ; /* ASCII name of registered driver */
253 char drvTag[64] ; /* revision string */
254 DbgEnd dbg_end ; /* function for debug closing */
255 DbgLog dbg_prt ; /* function for debug appending */
256 DbgOld dbg_old ; /* function for old debug appending */
257 DbgEv dbg_ev ; /* function for Windows NT Eventlog */
258 DbgIrq dbg_irq ; /* function for irql checked debug */
259 void *pReserved3 ;
260} _DbgHandle_ ;
261extern _DbgHandle_ myDriverDebugHandle ;
262typedef struct _OldDbgHandle_
263{ struct _OldDbgHandle_ *next ;
264 void *pIrp ;
265 long regTime[2] ;
266 unsigned long dbgMask ;
267 short id ;
268 char drvName[78] ;
269 DbgEnd dbg_end ;
270 DbgLog dbg_prt ;
271} _OldDbgHandle_ ;
272/* the differences in DbgHandles
273 old: tmp: new:
274 0 long next char Registered char Registered
275 char filler char Version
276 short id short id
277 4 long pIrp long regTime.lo long next
278 8 long regTime.lo long regTime.hi long regTime.lo
279 12 long regTime.hi long next long regTime.hi
280 16 long dbgMask long pIrp long pIrp
281 20 short id long dbgMask long dbgMask
282 22 char drvName[78] ..
283 24 .. char drvName[16] char drvName[16]
284 40 .. char drvTag[64] char drvTag[64]
285 100 void *dbg_end .. ..
286 104 void *dbg_prt void *dbg_end void *dbg_end
287 108 .. void *dbg_prt void *dbg_prt
288 112 .. .. void *dbg_old
289 116 .. .. void *dbg_ev
290 120 .. .. void *dbg_irq
291 124 .. .. void *pReserved3
292 ( new->id == 0 && *((short *)&new->dbgMask) == -1 ) identifies "old",
293 new->Registered and new->Version overlay old->next,
294 new->next overlays old->pIrp, new->regTime matches old->regTime and
295 thus these fields can be maintained in new struct whithout trouble;
296 id, dbgMask, drvName, dbg_end and dbg_prt need special handling !
297*/
298#define DBG_EXT_TYPE_CARD_TRACE 0x00000001
299typedef struct
300{
301 unsigned long ExtendedType;
302 union
303 {
304 /* DBG_EXT_TYPE_CARD_TRACE */
305 struct
306 {
307 void ( * MaskChangedNotify) (void *pContext);
308 unsigned long ModuleTxtMask;
309 unsigned long DebugLevel;
310 unsigned long B_ChannelMask;
311 unsigned long LogBufferSize;
312 } CardTrace;
313 }Data;
314} _DbgExtendedInfo_;
315#ifndef DIVA_NO_DEBUGLIB
316/* -------------------------------------------------------------
317 Function used for xlog-style debug
318 ------------------------------------------------------------- */
319#define XDI_USE_XLOG 1
320void xdi_dbg_xlog (char* x, ...);
321#endif /* DIVA_NO_DEBUGLIB */
322#endif /* __DEBUGLIB_H__ */
diff --git a/drivers/isdn/hardware/eicon/dfifo.h b/drivers/isdn/hardware/eicon/dfifo.h
new file mode 100644
index 000000000000..9a109c71e935
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/dfifo.h
@@ -0,0 +1,54 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef __DIVA_IDI_DFIFO_INC__
27#define __DIVA_IDI_DFIFO_INC__
28#define DIVA_DFIFO_CACHE_SZ 64 /* Used to isolate pipe from
29 rest of the world
30 should be divisible by 4
31 */
32#define DIVA_DFIFO_RAW_SZ (2512*8)
33#define DIVA_DFIFO_DATA_SZ 68
34#define DIVA_DFIFO_HDR_SZ 4
35#define DIVA_DFIFO_SEGMENT_SZ (DIVA_DFIFO_DATA_SZ+DIVA_DFIFO_HDR_SZ)
36#define DIVA_DFIFO_SEGMENTS ((DIVA_DFIFO_RAW_SZ)/(DIVA_DFIFO_SEGMENT_SZ)+1)
37#define DIVA_DFIFO_MEM_SZ (\
38 (DIVA_DFIFO_SEGMENT_SZ)*(DIVA_DFIFO_SEGMENTS)+\
39 (DIVA_DFIFO_CACHE_SZ)*2\
40 )
41#define DIVA_DFIFO_STEP DIVA_DFIFO_SEGMENT_SZ
42/* -------------------------------------------------------------------------
43 Block header layout is:
44 byte[0] -> flags
45 byte[1] -> length of data in block
46 byte[2] -> reserved
47 byte[4] -> reserved
48 ------------------------------------------------------------------------- */
49#define DIVA_DFIFO_WRAP 0x80 /* This is the last block in fifo */
50#define DIVA_DFIFO_READY 0x40 /* This block is ready for processing */
51#define DIVA_DFIFO_LAST 0x20 /* This block is last in message */
52#define DIVA_DFIFO_AUTO 0x10 /* Don't look for 'ready', don't ack */
53int diva_dfifo_create (void* start, int length);
54#endif
diff --git a/drivers/isdn/hardware/eicon/di.c b/drivers/isdn/hardware/eicon/di.c
new file mode 100644
index 000000000000..0617d7cabf06
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/di.c
@@ -0,0 +1,835 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#include "platform.h"
27#include "pc.h"
28#include "pr_pc.h"
29#include "di_defs.h"
30#include "di.h"
31#if !defined USE_EXTENDED_DEBUGS
32 #include "dimaint.h"
33#else
34 #define dprintf
35#endif
36#include "io.h"
37#include "dfifo.h"
38#define PR_RAM ((struct pr_ram *)0)
39#define RAM ((struct dual *)0)
40/*------------------------------------------------------------------*/
41/* local function prototypes */
42/*------------------------------------------------------------------*/
43void pr_out(ADAPTER * a);
44byte pr_dpc(ADAPTER * a);
45static byte pr_ready(ADAPTER * a);
46static byte isdn_rc(ADAPTER *, byte, byte, byte, word, dword, dword);
47static byte isdn_ind(ADAPTER *, byte, byte, byte, PBUFFER *, byte, word);
48/* -----------------------------------------------------------------
49 Functions used for the extended XDI Debug
50 macros
51 global convergence counter (used by all adapters)
52 Look by the implementation part of the functions
53 about the parameters.
54 If you change the dubugging parameters, then you should update
55 the aididbg.doc in the IDI doc's.
56 ----------------------------------------------------------------- */
57#if defined(XDI_USE_XLOG)
58#define XDI_A_NR(_x_) ((byte)(((ISDN_ADAPTER *)(_x_->io))->ANum))
59static void xdi_xlog (byte *msg, word code, int length);
60static byte xdi_xlog_sec = 0;
61#else
62#define XDI_A_NR(_x_) ((byte)0)
63#endif
64static void xdi_xlog_rc_event (byte Adapter,
65 byte Id, byte Ch, byte Rc, byte cb, byte type);
66static void xdi_xlog_request (byte Adapter, byte Id,
67 byte Ch, byte Req, byte type);
68static void xdi_xlog_ind (byte Adapter,
69 byte Id,
70 byte Ch,
71 byte Ind,
72 byte rnr_valid,
73 byte rnr,
74 byte type);
75/*------------------------------------------------------------------*/
76/* output function */
77/*------------------------------------------------------------------*/
78void pr_out(ADAPTER * a)
79{
80 byte e_no;
81 ENTITY * this = NULL;
82 BUFFERS *X;
83 word length;
84 word i;
85 word clength;
86 REQ * ReqOut;
87 byte more;
88 byte ReadyCount;
89 byte ReqCount;
90 byte Id;
91 dtrc(dprintf("pr_out"));
92 /* while a request is pending ... */
93 e_no = look_req(a);
94 if(!e_no)
95 {
96 dtrc(dprintf("no_req"));
97 return;
98 }
99 ReadyCount = pr_ready(a);
100 if(!ReadyCount)
101 {
102 dtrc(dprintf("not_ready"));
103 return;
104 }
105 ReqCount = 0;
106 while(e_no && ReadyCount) {
107 next_req(a);
108 this = entity_ptr(a, e_no);
109#ifdef USE_EXTENDED_DEBUGS
110 if ( !this )
111 {
112 DBG_FTL(("XDI: [%02x] !A%d ==> NULL entity ptr - try to ignore",
113 xdi_xlog_sec++, (int)((ISDN_ADAPTER *)a->io)->ANum))
114 e_no = look_req(a) ;
115 ReadyCount-- ;
116 continue ;
117 }
118 {
119 DBG_TRC((">A%d Id=0x%x Req=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, this->Id, this->Req))
120 }
121#else
122 dbug(dprintf("out:Req=%x,Id=%x,Ch=%x",this->Req,this->Id,this->ReqCh));
123#endif
124 /* get address of next available request buffer */
125 ReqOut = (REQ *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextReq)];
126#if defined(DIVA_ISTREAM)
127 if (!(a->tx_stream[this->Id] &&
128 this->Req == N_DATA)) {
129#endif
130 /* now copy the data from the current data buffer into the */
131 /* adapters request buffer */
132 length = 0;
133 i = this->XCurrent;
134 X = PTR_X(a,this);
135 while(i<this->XNum && length<270) {
136 clength = MIN((word)(270-length),X[i].PLength-this->XOffset);
137 a->ram_out_buffer(a,
138 &ReqOut->XBuffer.P[length],
139 PTR_P(a,this,&X[i].P[this->XOffset]),
140 clength);
141 length +=clength;
142 this->XOffset +=clength;
143 if(this->XOffset==X[i].PLength) {
144 this->XCurrent = (byte)++i;
145 this->XOffset = 0;
146 }
147 }
148#if defined(DIVA_ISTREAM)
149 } else { /* Use CMA extension in order to transfer data to the card */
150 i = this->XCurrent;
151 X = PTR_X(a,this);
152 while (i < this->XNum) {
153 diva_istream_write (a,
154 this->Id,
155 PTR_P(a,this,&X[i].P[0]),
156 X[i].PLength,
157 ((i+1) == this->XNum),
158 0, 0);
159 this->XCurrent = (byte)++i;
160 }
161 length = 0;
162 }
163#endif
164 a->ram_outw(a, &ReqOut->XBuffer.length, length);
165 a->ram_out(a, &ReqOut->ReqId, this->Id);
166 a->ram_out(a, &ReqOut->ReqCh, this->ReqCh);
167 /* if it's a specific request (no ASSIGN) ... */
168 if(this->Id &0x1f) {
169 /* if buffers are left in the list of data buffers do */
170 /* do chaining (LL_MDATA, N_MDATA) */
171 this->More++;
172 if(i<this->XNum && this->MInd) {
173 xdi_xlog_request (XDI_A_NR(a), this->Id, this->ReqCh, this->MInd,
174 a->IdTypeTable[this->No]);
175 a->ram_out(a, &ReqOut->Req, this->MInd);
176 more = TRUE;
177 }
178 else {
179 xdi_xlog_request (XDI_A_NR(a), this->Id, this->ReqCh, this->Req,
180 a->IdTypeTable[this->No]);
181 this->More |=XMOREF;
182 a->ram_out(a, &ReqOut->Req, this->Req);
183 more = FALSE;
184 if (a->FlowControlIdTable[this->ReqCh] == this->Id)
185 a->FlowControlSkipTable[this->ReqCh] = TRUE;
186 /*
187 Note that remove request was sent to the card
188 */
189 if (this->Req == REMOVE) {
190 a->misc_flags_table[e_no] |= DIVA_MISC_FLAGS_REMOVE_PENDING;
191 }
192 }
193 /* if we did chaining, this entity is put back into the */
194 /* request queue */
195 if(more) {
196 req_queue(a,this->No);
197 }
198 }
199 /* else it's a ASSIGN */
200 else {
201 /* save the request code used for buffer chaining */
202 this->MInd = 0;
203 if (this->Id==BLLC_ID) this->MInd = LL_MDATA;
204 if (this->Id==NL_ID ||
205 this->Id==TASK_ID ||
206 this->Id==MAN_ID
207 ) this->MInd = N_MDATA;
208 /* send the ASSIGN */
209 a->IdTypeTable[this->No] = this->Id;
210 xdi_xlog_request (XDI_A_NR(a),this->Id,this->ReqCh,this->Req, this->Id);
211 this->More |=XMOREF;
212 a->ram_out(a, &ReqOut->Req, this->Req);
213 /* save the reference of the ASSIGN */
214 assign_queue(a, this->No, a->ram_inw(a, &ReqOut->Reference));
215 }
216 a->ram_outw(a, &PR_RAM->NextReq, a->ram_inw(a, &ReqOut->next));
217 ReadyCount--;
218 ReqCount++;
219 e_no = look_req(a);
220 }
221 /* send the filled request buffers to the ISDN adapter */
222 a->ram_out(a, &PR_RAM->ReqInput,
223 (byte)(a->ram_in(a, &PR_RAM->ReqInput) + ReqCount));
224 /* if it is a 'unreturncoded' UREMOVE request, remove the */
225 /* Id from our table after sending the request */
226 if(this && (this->Req==UREMOVE) && this->Id) {
227 Id = this->Id;
228 e_no = a->IdTable[Id];
229 free_entity(a, e_no);
230 for (i = 0; i < 256; i++)
231 {
232 if (a->FlowControlIdTable[i] == Id)
233 a->FlowControlIdTable[i] = 0;
234 }
235 a->IdTable[Id] = 0;
236 this->Id = 0;
237 }
238}
239static byte pr_ready(ADAPTER * a)
240{
241 byte ReadyCount;
242 ReadyCount = (byte)(a->ram_in(a, &PR_RAM->ReqOutput) -
243 a->ram_in(a, &PR_RAM->ReqInput));
244 if(!ReadyCount) {
245 if(!a->ReadyInt) {
246 a->ram_inc(a, &PR_RAM->ReadyInt);
247 a->ReadyInt++;
248 }
249 }
250 return ReadyCount;
251}
252/*------------------------------------------------------------------*/
253/* isdn interrupt handler */
254/*------------------------------------------------------------------*/
255byte pr_dpc(ADAPTER * a)
256{
257 byte Count;
258 RC * RcIn;
259 IND * IndIn;
260 byte c;
261 byte RNRId;
262 byte Rc;
263 byte Ind;
264 /* if return codes are available ... */
265 if((Count = a->ram_in(a, &PR_RAM->RcOutput)) != 0) {
266 dtrc(dprintf("#Rc=%x",Count));
267 /* get the buffer address of the first return code */
268 RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextRc)];
269 /* for all return codes do ... */
270 while(Count--) {
271 if((Rc=a->ram_in(a, &RcIn->Rc)) != 0) {
272 dword tmp[2];
273 /*
274 Get extended information, associated with return code
275 */
276 a->ram_in_buffer(a,
277 &RcIn->Reserved2[0],
278 (byte*)&tmp[0],
279 8);
280 /* call return code handler, if it is not our return code */
281 /* the handler returns 2 */
282 /* for all return codes we process, we clear the Rc field */
283 isdn_rc(a,
284 Rc,
285 a->ram_in(a, &RcIn->RcId),
286 a->ram_in(a, &RcIn->RcCh),
287 a->ram_inw(a, &RcIn->Reference),
288 tmp[0], /* type of extended informtion */
289 tmp[1]); /* extended information */
290 a->ram_out(a, &RcIn->Rc, 0);
291 }
292 /* get buffer address of next return code */
293 RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &RcIn->next)];
294 }
295 /* clear all return codes (no chaining!) */
296 a->ram_out(a, &PR_RAM->RcOutput ,0);
297 /* call output function */
298 pr_out(a);
299 }
300 /* clear RNR flag */
301 RNRId = 0;
302 /* if indications are available ... */
303 if((Count = a->ram_in(a, &PR_RAM->IndOutput)) != 0) {
304 dtrc(dprintf("#Ind=%x",Count));
305 /* get the buffer address of the first indication */
306 IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextInd)];
307 /* for all indications do ... */
308 while(Count--) {
309 /* if the application marks an indication as RNR, all */
310 /* indications from the same Id delivered in this interrupt */
311 /* are marked RNR */
312 if(RNRId && RNRId==a->ram_in(a, &IndIn->IndId)) {
313 a->ram_out(a, &IndIn->Ind, 0);
314 a->ram_out(a, &IndIn->RNR, TRUE);
315 }
316 else {
317 Ind = a->ram_in(a, &IndIn->Ind);
318 if(Ind) {
319 RNRId = 0;
320 /* call indication handler, a return value of 2 means chain */
321 /* a return value of 1 means RNR */
322 /* for all indications we process, we clear the Ind field */
323 c = isdn_ind(a,
324 Ind,
325 a->ram_in(a, &IndIn->IndId),
326 a->ram_in(a, &IndIn->IndCh),
327 &IndIn->RBuffer,
328 a->ram_in(a, &IndIn->MInd),
329 a->ram_inw(a, &IndIn->MLength));
330 if(c==1) {
331 dtrc(dprintf("RNR"));
332 a->ram_out(a, &IndIn->Ind, 0);
333 RNRId = a->ram_in(a, &IndIn->IndId);
334 a->ram_out(a, &IndIn->RNR, TRUE);
335 }
336 }
337 }
338 /* get buffer address of next indication */
339 IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &IndIn->next)];
340 }
341 a->ram_out(a, &PR_RAM->IndOutput, 0);
342 }
343 return FALSE;
344}
345byte scom_test_int(ADAPTER * a)
346{
347 return a->ram_in(a,(void *)0x3fe);
348}
349void scom_clear_int(ADAPTER * a)
350{
351 a->ram_out(a,(void *)0x3fe,0);
352}
353/*------------------------------------------------------------------*/
354/* return code handler */
355/*------------------------------------------------------------------*/
356byte isdn_rc(ADAPTER * a,
357 byte Rc,
358 byte Id,
359 byte Ch,
360 word Ref,
361 dword extended_info_type,
362 dword extended_info)
363{
364 ENTITY * this;
365 byte e_no;
366 word i;
367 int cancel_rc;
368#ifdef USE_EXTENDED_DEBUGS
369 {
370 DBG_TRC(("<A%d Id=0x%x Rc=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, Id, Rc))
371 }
372#else
373 dbug(dprintf("isdn_rc(Rc=%x,Id=%x,Ch=%x)",Rc,Id,Ch));
374#endif
375 /* check for ready interrupt */
376 if(Rc==READY_INT) {
377 xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 0, 0);
378 if(a->ReadyInt) {
379 a->ReadyInt--;
380 return 0;
381 }
382 return 2;
383 }
384 /* if we know this Id ... */
385 e_no = a->IdTable[Id];
386 if(e_no) {
387 this = entity_ptr(a,e_no);
388 xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 0, a->IdTypeTable[this->No]);
389 this->RcCh = Ch;
390 /* if it is a return code to a REMOVE request, remove the */
391 /* Id from our table */
392 if ((a->misc_flags_table[e_no] & DIVA_MISC_FLAGS_REMOVE_PENDING) &&
393 (Rc==OK)) {
394 if (a->IdTypeTable[e_no] == NL_ID) {
395 if (a->RcExtensionSupported &&
396 (extended_info_type != DIVA_RC_TYPE_REMOVE_COMPLETE)) {
397 dtrc(dprintf("XDI: N-REMOVE, A(%02x) Id:%02x, ignore RC=OK",
398 XDI_A_NR(a),Id));
399 return (0);
400 }
401 if (extended_info_type == DIVA_RC_TYPE_REMOVE_COMPLETE)
402 a->RcExtensionSupported = TRUE;
403 }
404 a->misc_flags_table[e_no] &= ~DIVA_MISC_FLAGS_REMOVE_PENDING;
405 a->misc_flags_table[e_no] &= ~DIVA_MISC_FLAGS_NO_RC_CANCELLING;
406 free_entity(a, e_no);
407 for (i = 0; i < 256; i++)
408 {
409 if (a->FlowControlIdTable[i] == Id)
410 a->FlowControlIdTable[i] = 0;
411 }
412 a->IdTable[Id] = 0;
413 this->Id = 0;
414 /* ---------------------------------------------------------------
415 If we send N_DISC or N_DISK_ACK after we have received OK_FC
416 then the card will respond with OK_FC and later with RC==OK.
417 If we send N_REMOVE in this state we will receive only RC==OK
418 This will create the state in that the XDI is waiting for the
419 additional RC and does not delivery the RC to the client. This
420 code corrects the counter of outstanding RC's in this case.
421 --------------------------------------------------------------- */
422 if ((this->More & XMOREC) > 1) {
423 this->More &= ~XMOREC;
424 this->More |= 1;
425 dtrc(dprintf("XDI: correct MORE on REMOVE A(%02x) Id:%02x",
426 XDI_A_NR(a),Id));
427 }
428 }
429 if (Rc==OK_FC) {
430 a->FlowControlIdTable[Ch] = Id;
431 a->FlowControlSkipTable[Ch] = FALSE;
432 this->Rc = Rc;
433 this->More &= ~(XBUSY | XMOREC);
434 this->complete=0xff;
435 xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
436 CALLBACK(a, this);
437 return 0;
438 }
439 /*
440 New protocol code sends return codes that comes from release
441 of flow control condition marked with DIVA_RC_TYPE_OK_FC extended
442 information element type.
443 If like return code arrives then application is able to process
444 all return codes self and XDI should not cances return codes.
445 This return code does not decrement XMOREC partial return code
446 counter due to fact that it was no request for this return code,
447 also XMOREC was not incremented.
448 */
449 if (extended_info_type == DIVA_RC_TYPE_OK_FC) {
450 a->misc_flags_table[e_no] |= DIVA_MISC_FLAGS_NO_RC_CANCELLING;
451 this->Rc = Rc;
452 this->complete=0xff;
453 xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
454 DBG_TRC(("XDI OK_FC A(%02x) Id:%02x Ch:%02x Rc:%02x",
455 XDI_A_NR(a), Id, Ch, Rc))
456 CALLBACK(a, this);
457 return 0;
458 }
459 cancel_rc = !(a->misc_flags_table[e_no] & DIVA_MISC_FLAGS_NO_RC_CANCELLING);
460 if (cancel_rc && (a->FlowControlIdTable[Ch] == Id))
461 {
462 a->FlowControlIdTable[Ch] = 0;
463 if ((Rc != OK) || !a->FlowControlSkipTable[Ch])
464 {
465 this->Rc = Rc;
466 if (Ch == this->ReqCh)
467 {
468 this->More &=~(XBUSY | XMOREC);
469 this->complete=0xff;
470 }
471 xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
472 CALLBACK(a, this);
473 }
474 return 0;
475 }
476 if (this->More &XMOREC)
477 this->More--;
478 /* call the application callback function */
479 if (((!cancel_rc) || (this->More & XMOREF)) && !(this->More & XMOREC)) {
480 this->Rc = Rc;
481 this->More &=~XBUSY;
482 this->complete=0xff;
483 xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
484 CALLBACK(a, this);
485 }
486 return 0;
487 }
488 /* if it's an ASSIGN return code check if it's a return */
489 /* code to an ASSIGN request from us */
490 if((Rc &0xf0)==ASSIGN_RC) {
491 e_no = get_assign(a, Ref);
492 if(e_no) {
493 this = entity_ptr(a,e_no);
494 this->Id = Id;
495 xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 2, a->IdTypeTable[this->No]);
496 /* call the application callback function */
497 this->Rc = Rc;
498 this->More &=~XBUSY;
499 this->complete=0xff;
500#if defined(DIVA_ISTREAM) /* { */
501 if ((Rc == ASSIGN_OK) && a->ram_offset &&
502 (a->IdTypeTable[this->No] == NL_ID) &&
503 ((extended_info_type == DIVA_RC_TYPE_RX_DMA) ||
504 (extended_info_type == DIVA_RC_TYPE_CMA_PTR)) &&
505 extended_info) {
506 dword offset = (*(a->ram_offset)) (a);
507 dword tmp[2];
508 extended_info -= offset;
509#ifdef PLATFORM_GT_32BIT
510 a->ram_in_dw(a, (void*)ULongToPtr(extended_info), (dword*)&tmp[0], 2);
511#else
512 a->ram_in_dw(a, (void*)extended_info, (dword*)&tmp[0], 2);
513#endif
514 a->tx_stream[Id] = tmp[0];
515 a->rx_stream[Id] = tmp[1];
516 if (extended_info_type == DIVA_RC_TYPE_RX_DMA) {
517 DBG_TRC(("Id=0x%x RxDMA=%08x:%08x",
518 Id, a->tx_stream[Id], a->rx_stream[Id]))
519 a->misc_flags_table[this->No] |= DIVA_MISC_FLAGS_RX_DMA;
520 } else {
521 DBG_TRC(("Id=0x%x CMA=%08x:%08x",
522 Id, a->tx_stream[Id], a->rx_stream[Id]))
523 a->misc_flags_table[this->No] &= ~DIVA_MISC_FLAGS_RX_DMA;
524 a->rx_pos[Id] = 0;
525 a->rx_stream[Id] -= offset;
526 }
527 a->tx_pos[Id] = 0;
528 a->tx_stream[Id] -= offset;
529 } else {
530 a->tx_stream[Id] = 0;
531 a->rx_stream[Id] = 0;
532 a->misc_flags_table[this->No] &= ~DIVA_MISC_FLAGS_RX_DMA;
533 }
534#endif /* } */
535 CALLBACK(a, this);
536 if(Rc==ASSIGN_OK) {
537 a->IdTable[Id] = e_no;
538 }
539 else
540 {
541 free_entity(a, e_no);
542 for (i = 0; i < 256; i++)
543 {
544 if (a->FlowControlIdTable[i] == Id)
545 a->FlowControlIdTable[i] = 0;
546 }
547 a->IdTable[Id] = 0;
548 this->Id = 0;
549 }
550 return 1;
551 }
552 }
553 return 2;
554}
555/*------------------------------------------------------------------*/
556/* indication handler */
557/*------------------------------------------------------------------*/
558byte isdn_ind(ADAPTER * a,
559 byte Ind,
560 byte Id,
561 byte Ch,
562 PBUFFER * RBuffer,
563 byte MInd,
564 word MLength)
565{
566 ENTITY * this;
567 word clength;
568 word offset;
569 BUFFERS *R;
570 byte* cma = NULL;
571#ifdef USE_EXTENDED_DEBUGS
572 {
573 DBG_TRC(("<A%d Id=0x%x Ind=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, Id, Ind))
574 }
575#else
576 dbug(dprintf("isdn_ind(Ind=%x,Id=%x,Ch=%x)",Ind,Id,Ch));
577#endif
578 if(a->IdTable[Id]) {
579 this = entity_ptr(a,a->IdTable[Id]);
580 this->IndCh = Ch;
581 xdi_xlog_ind (XDI_A_NR(a), Id, Ch, Ind,
582 0/* rnr_valid */, 0 /* rnr */, a->IdTypeTable[this->No]);
583 /* if the Receive More flag is not yet set, this is the */
584 /* first buffer of the packet */
585 if(this->RCurrent==0xff) {
586 /* check for receive buffer chaining */
587 if(Ind==this->MInd) {
588 this->complete = 0;
589 this->Ind = MInd;
590 }
591 else {
592 this->complete = 1;
593 this->Ind = Ind;
594 }
595 /* call the application callback function for the receive */
596 /* look ahead */
597 this->RLength = MLength;
598#if defined(DIVA_ISTREAM)
599 if ((a->rx_stream[this->Id] ||
600 (a->misc_flags_table[this->No] & DIVA_MISC_FLAGS_RX_DMA)) &&
601 ((Ind == N_DATA) ||
602 (a->protocol_capabilities & PROTCAP_CMA_ALLPR))) {
603 PISDN_ADAPTER IoAdapter = (PISDN_ADAPTER)a->io ;
604 if (a->misc_flags_table[this->No] & DIVA_MISC_FLAGS_RX_DMA) {
605#if defined(DIVA_IDI_RX_DMA)
606 dword d;
607 diva_get_dma_map_entry (\
608 (struct _diva_dma_map_entry*)IoAdapter->dma_map,
609 (int)a->rx_stream[this->Id], (void**)&cma, &d);
610#else
611 cma = &a->stream_buffer[0];
612 cma[0] = cma[1] = cma[2] = cma[3] = 0;
613#endif
614 this->RLength = MLength = (word)*(dword*)cma;
615 cma += 4;
616 } else {
617 int final = 0;
618 cma = &a->stream_buffer[0];
619 this->RLength = MLength = (word)diva_istream_read (a,
620 Id,
621 cma,
622 sizeof(a->stream_buffer),
623 &final, NULL, NULL);
624 }
625 IoAdapter->RBuffer.length = MIN(MLength, 270);
626 if (IoAdapter->RBuffer.length != MLength) {
627 this->complete = 0;
628 } else {
629 this->complete = 1;
630 }
631 memcpy (IoAdapter->RBuffer.P, cma, IoAdapter->RBuffer.length) ;
632 this->RBuffer = (DBUFFER *)&IoAdapter->RBuffer ;
633 }
634#endif
635 if (!cma) {
636 a->ram_look_ahead(a, RBuffer, this);
637 }
638 this->RNum = 0;
639 CALLBACK(a, this);
640 /* map entity ptr, selector could be re-mapped by call to */
641 /* IDI from within callback */
642 this = entity_ptr(a,a->IdTable[Id]);
643 xdi_xlog_ind (XDI_A_NR(a), Id, Ch, Ind,
644 1/* rnr_valid */, this->RNR/* rnr */, a->IdTypeTable[this->No]);
645 /* check for RNR */
646 if(this->RNR==1) {
647 this->RNR = 0;
648 return 1;
649 }
650 /* if no buffers are provided by the application, the */
651 /* application want to copy the data itself including */
652 /* N_MDATA/LL_MDATA chaining */
653 if(!this->RNR && !this->RNum) {
654 xdi_xlog_ind (XDI_A_NR(a), Id, Ch, Ind,
655 2/* rnr_valid */, 0/* rnr */, a->IdTypeTable[this->No]);
656 return 0;
657 }
658 /* if there is no RNR, set the More flag */
659 this->RCurrent = 0;
660 this->ROffset = 0;
661 }
662 if(this->RNR==2) {
663 if(Ind!=this->MInd) {
664 this->RCurrent = 0xff;
665 this->RNR = 0;
666 }
667 return 0;
668 }
669 /* if we have received buffers from the application, copy */
670 /* the data into these buffers */
671 offset = 0;
672 R = PTR_R(a,this);
673 do {
674 if(this->ROffset==R[this->RCurrent].PLength) {
675 this->ROffset = 0;
676 this->RCurrent++;
677 }
678 if (cma) {
679 clength = MIN(MLength, R[this->RCurrent].PLength-this->ROffset);
680 } else {
681 clength = MIN(a->ram_inw(a, &RBuffer->length)-offset,
682 R[this->RCurrent].PLength-this->ROffset);
683 }
684 if(R[this->RCurrent].P) {
685 if (cma) {
686 memcpy (PTR_P(a,this,&R[this->RCurrent].P[this->ROffset]),
687 &cma[offset],
688 clength);
689 } else {
690 a->ram_in_buffer(a,
691 &RBuffer->P[offset],
692 PTR_P(a,this,&R[this->RCurrent].P[this->ROffset]),
693 clength);
694 }
695 }
696 offset +=clength;
697 this->ROffset +=clength;
698 if (cma) {
699 if (offset >= MLength) {
700 break;
701 }
702 continue;
703 }
704 } while(offset<(a->ram_inw(a, &RBuffer->length)));
705 /* if it's the last buffer of the packet, call the */
706 /* application callback function for the receive complete */
707 /* call */
708 if(Ind!=this->MInd) {
709 R[this->RCurrent].PLength = this->ROffset;
710 if(this->ROffset) this->RCurrent++;
711 this->RNum = this->RCurrent;
712 this->RCurrent = 0xff;
713 this->Ind = Ind;
714 this->complete = 2;
715 xdi_xlog_ind (XDI_A_NR(a), Id, Ch, Ind,
716 3/* rnr_valid */, 0/* rnr */, a->IdTypeTable[this->No]);
717 CALLBACK(a, this);
718 }
719 return 0;
720 }
721 return 2;
722}
723#if defined(XDI_USE_XLOG)
724/* -----------------------------------------------------------
725 This function works in the same way as xlog on the
726 active board
727 ----------------------------------------------------------- */
728static void xdi_xlog (byte *msg, word code, int length) {
729 xdi_dbg_xlog ("\x00\x02", msg, code, length);
730}
731#endif
732/* -----------------------------------------------------------
733 This function writes the information about the Return Code
734 processing in the trace buffer. Trace ID is 221.
735 INPUT:
736 Adapter - system unicue adapter number (0 ... 255)
737 Id - Id of the entity that had sent this return code
738 Ch - Channel of the entity that had sent this return code
739 Rc - return code value
740 cb: (0...2)
741 switch (cb) {
742 case 0: printf ("DELIVERY"); break;
743 case 1: printf ("CALLBACK"); break;
744 case 2: printf ("ASSIGN"); break;
745 }
746 DELIVERY - have entered isdn_rc with this RC
747 CALLBACK - about to make callback to the application
748 for this RC
749 ASSIGN - about to make callback for RC that is result
750 of ASSIGN request. It is no DELIVERY message
751 before of this message
752 type - the Id that was sent by the ASSIGN of this entity.
753 This should be global Id like NL_ID, DSIG_ID, MAN_ID.
754 An unknown Id will cause "?-" in the front of the request.
755 In this case the log.c is to be extended.
756 ----------------------------------------------------------- */
757static void xdi_xlog_rc_event (byte Adapter,
758 byte Id, byte Ch, byte Rc, byte cb, byte type) {
759#if defined(XDI_USE_XLOG)
760 word LogInfo[4];
761 PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8)));
762 PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8)));
763 PUT_WORD(&LogInfo[2], ((word)Rc | (word)(type << 8)));
764 PUT_WORD(&LogInfo[3], cb);
765 xdi_xlog ((byte*)&LogInfo[0], 221, sizeof(LogInfo));
766#endif
767}
768/* ------------------------------------------------------------------------
769 This function writes the information about the request processing
770 in the trace buffer. Trace ID is 220.
771 INPUT:
772 Adapter - system unicue adapter number (0 ... 255)
773 Id - Id of the entity that had sent this request
774 Ch - Channel of the entity that had sent this request
775 Req - Code of the request
776 type - the Id that was sent by the ASSIGN of this entity.
777 This should be global Id like NL_ID, DSIG_ID, MAN_ID.
778 An unknown Id will cause "?-" in the front of the request.
779 In this case the log.c is to be extended.
780 ------------------------------------------------------------------------ */
781static void xdi_xlog_request (byte Adapter, byte Id,
782 byte Ch, byte Req, byte type) {
783#if defined(XDI_USE_XLOG)
784 word LogInfo[3];
785 PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8)));
786 PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8)));
787 PUT_WORD(&LogInfo[2], ((word)Req | (word)(type << 8)));
788 xdi_xlog ((byte*)&LogInfo[0], 220, sizeof(LogInfo));
789#endif
790}
791/* ------------------------------------------------------------------------
792 This function writes the information about the indication processing
793 in the trace buffer. Trace ID is 222.
794 INPUT:
795 Adapter - system unicue adapter number (0 ... 255)
796 Id - Id of the entity that had sent this indication
797 Ch - Channel of the entity that had sent this indication
798 Ind - Code of the indication
799 rnr_valid: (0 .. 3) supported
800 switch (rnr_valid) {
801 case 0: printf ("DELIVERY"); break;
802 case 1: printf ("RNR=%d", rnr);
803 case 2: printf ("RNum=0");
804 case 3: printf ("COMPLETE");
805 }
806 DELIVERY - indication entered isdn_rc function
807 RNR=... - application had returned RNR=... after the
808 look ahead callback
809 RNum=0 - aplication had not returned any buffer to copy
810 this indication and will copy it self
811 COMPLETE - XDI had copied the data to the buffers provided
812 bu the application and is about to issue the
813 final callback
814 rnr: Look case 1 of the rnr_valid
815 type: the Id that was sent by the ASSIGN of this entity. This should
816 be global Id like NL_ID, DSIG_ID, MAN_ID. An unknown Id will
817 cause "?-" in the front of the request. In this case the
818 log.c is to be extended.
819 ------------------------------------------------------------------------ */
820static void xdi_xlog_ind (byte Adapter,
821 byte Id,
822 byte Ch,
823 byte Ind,
824 byte rnr_valid,
825 byte rnr,
826 byte type) {
827#if defined(XDI_USE_XLOG)
828 word LogInfo[4];
829 PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8)));
830 PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8)));
831 PUT_WORD(&LogInfo[2], ((word)Ind | (word)(type << 8)));
832 PUT_WORD(&LogInfo[3], ((word)rnr | (word)(rnr_valid << 8)));
833 xdi_xlog ((byte*)&LogInfo[0], 222, sizeof(LogInfo));
834#endif
835}
diff --git a/drivers/isdn/hardware/eicon/di.h b/drivers/isdn/hardware/eicon/di.h
new file mode 100644
index 000000000000..dcf37b10f5dc
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/di.h
@@ -0,0 +1,118 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26/*
27 * some macros for detailed trace management
28 */
29#include "di_dbg.h"
30/*****************************************************************************/
31#define XMOREC 0x1f
32#define XMOREF 0x20
33#define XBUSY 0x40
34#define RMORE 0x80
35#define DIVA_MISC_FLAGS_REMOVE_PENDING 0x01
36#define DIVA_MISC_FLAGS_NO_RC_CANCELLING 0x02
37#define DIVA_MISC_FLAGS_RX_DMA 0x04
38 /* structure for all information we have to keep on a per */
39 /* adapater basis */
40typedef struct adapter_s ADAPTER;
41struct adapter_s {
42 void * io;
43 byte IdTable[256];
44 byte IdTypeTable[256];
45 byte FlowControlIdTable[256];
46 byte FlowControlSkipTable[256];
47 byte ReadyInt;
48 byte RcExtensionSupported;
49 byte misc_flags_table[256];
50 dword protocol_capabilities;
51 byte ( * ram_in)(ADAPTER * a, void * adr);
52 word ( * ram_inw)(ADAPTER * a, void * adr);
53 void (* ram_in_buffer)(ADAPTER * a, void * adr, void * P, word length);
54 void (* ram_look_ahead)(ADAPTER * a, PBUFFER * RBuffer, ENTITY * e);
55 void ( * ram_out)(ADAPTER * a, void * adr, byte data);
56 void ( * ram_outw)(ADAPTER * a, void * adr, word data);
57 void (* ram_out_buffer)(ADAPTER * a, void * adr, void * P, word length);
58 void ( * ram_inc)(ADAPTER * a, void * adr);
59#if defined(DIVA_ISTREAM)
60 dword rx_stream[256];
61 dword tx_stream[256];
62 word tx_pos[256];
63 word rx_pos[256];
64 byte stream_buffer[2512];
65 dword ( * ram_offset)(ADAPTER * a);
66 void ( * ram_out_dw) (ADAPTER *a,
67 void *addr,
68 const dword* data,
69 int dwords);
70 void ( * ram_in_dw) (ADAPTER *a,
71 void *addr,
72 dword* data,
73 int dwords);
74 void ( * istream_wakeup)(ADAPTER* a);
75#else
76 byte stream_buffer[4];
77#endif
78};
79/*------------------------------------------------------------------*/
80/* public functions of IDI common code */
81/*------------------------------------------------------------------*/
82void pr_out(ADAPTER * a);
83byte pr_dpc(ADAPTER * a);
84byte scom_test_int(ADAPTER * a);
85void scom_clear_int(ADAPTER * a);
86/*------------------------------------------------------------------*/
87/* OS specific functions used by IDI common code */
88/*------------------------------------------------------------------*/
89void free_entity(ADAPTER * a, byte e_no);
90void assign_queue(ADAPTER * a, byte e_no, word ref);
91byte get_assign(ADAPTER * a, word ref);
92void req_queue(ADAPTER * a, byte e_no);
93byte look_req(ADAPTER * a);
94void next_req(ADAPTER * a);
95ENTITY * entity_ptr(ADAPTER * a, byte e_no);
96#if defined(DIVA_ISTREAM)
97struct _diva_xdi_stream_interface;
98void diva_xdi_provide_istream_info (ADAPTER* a,
99 struct _diva_xdi_stream_interface* pI);
100void pr_stream (ADAPTER * a);
101int diva_istream_write (void* context,
102 int Id,
103 void* data,
104 int length,
105 int final,
106 byte usr1,
107 byte usr2);
108int diva_istream_read (void* context,
109 int Id,
110 void* data,
111 int max_length,
112 int* final,
113 byte* usr1,
114 byte* usr2);
115#if defined(DIVA_IDI_RX_DMA)
116#include "diva_dma.h"
117#endif
118#endif
diff --git a/drivers/isdn/hardware/eicon/di_dbg.h b/drivers/isdn/hardware/eicon/di_dbg.h
new file mode 100644
index 000000000000..d576ff31d44c
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/di_dbg.h
@@ -0,0 +1,37 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef __DIVA_DI_DBG_INC__
27#define __DIVA_DI_DBG_INC__
28#if !defined (dtrc)
29#define dtrc(a)
30#endif
31#if !defined (dbug)
32#define dbug(a)
33#endif
34#if !defined USE_EXTENDED_DEBUGS
35extern void (*dprintf)(char*, ...);
36#endif
37#endif
diff --git a/drivers/isdn/hardware/eicon/di_defs.h b/drivers/isdn/hardware/eicon/di_defs.h
new file mode 100644
index 000000000000..4c2f61267df1
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/di_defs.h
@@ -0,0 +1,181 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef _DI_DEFS_
27#define _DI_DEFS_
28 /* typedefs for our data structures */
29typedef struct get_name_s GET_NAME;
30/* The entity_s structure is used to pass all
31 parameters between application and IDI */
32typedef struct entity_s ENTITY;
33typedef struct buffers_s BUFFERS;
34typedef struct postcall_s POSTCALL;
35typedef struct get_para_s GET_PARA;
36#define BOARD_NAME_LENGTH 9
37#define IDI_CALL_LINK_T
38#define IDI_CALL_ENTITY_T
39/* typedef void ( * IDI_CALL)(ENTITY *); */
40/* --------------------------------------------------------
41 IDI_CALL
42 -------------------------------------------------------- */
43typedef void (IDI_CALL_LINK_T * IDI_CALL)(ENTITY IDI_CALL_ENTITY_T *);
44typedef struct {
45 word length; /* length of data/parameter field */
46 byte P[270]; /* data/parameter field */
47} DBUFFER;
48struct get_name_s {
49 word command; /* command = 0x0100 */
50 byte name[BOARD_NAME_LENGTH];
51};
52struct postcall_s {
53 word command; /* command = 0x0300 */
54 word dummy; /* not used */
55 void ( * callback)(void *); /* call back */
56 void *context; /* context pointer */
57};
58#define REQ_PARA 0x0600 /* request command line parameters */
59#define REQ_PARA_LEN 1 /* number of data bytes */
60#define L1_STARTUP_DOWN_POS 0 /* '-y' command line parameter in......*/
61#define L1_STARTUP_DOWN_MSK 0x01 /* first byte position (index 0) with value 0x01 */
62struct get_para_s {
63 word command; /* command = 0x0600 */
64 byte len; /* max length of para field in bytes */
65 byte para[REQ_PARA_LEN]; /* parameter field */
66};
67struct buffers_s {
68 word PLength;
69 byte * P;
70};
71struct entity_s {
72 byte Req; /* pending request */
73 byte Rc; /* return code received */
74 byte Ind; /* indication received */
75 byte ReqCh; /* channel of current Req */
76 byte RcCh; /* channel of current Rc */
77 byte IndCh; /* channel of current Ind */
78 byte Id; /* ID used by this entity */
79 byte GlobalId; /* reserved field */
80 byte XNum; /* number of X-buffers */
81 byte RNum; /* number of R-buffers */
82 BUFFERS * X; /* pointer to X-buffer list */
83 BUFFERS * R; /* pointer to R-buffer list */
84 word RLength; /* length of current R-data */
85 DBUFFER * RBuffer; /* buffer of current R-data */
86 byte RNR; /* receive not ready flag */
87 byte complete; /* receive complete status */
88 IDI_CALL callback;
89 word user[2];
90 /* fields used by the driver internally */
91 byte No; /* entity number */
92 byte reserved2; /* reserved field */
93 byte More; /* R/X More flags */
94 byte MInd; /* MDATA coding for this ID */
95 byte XCurrent; /* current transmit buffer */
96 byte RCurrent; /* current receive buffer */
97 word XOffset; /* offset in x-buffer */
98 word ROffset; /* offset in r-buffer */
99};
100typedef struct {
101 byte type;
102 byte channels;
103 word features;
104 IDI_CALL request;
105} DESCRIPTOR;
106 /* descriptor type field coding */
107#define IDI_ADAPTER_S 1
108#define IDI_ADAPTER_PR 2
109#define IDI_ADAPTER_DIVA 3
110#define IDI_ADAPTER_MAESTRA 4
111#define IDI_VADAPTER 0x40
112#define IDI_DRIVER 0x80
113#define IDI_DADAPTER 0xfd
114#define IDI_DIDDPNP 0xfe
115#define IDI_DIMAINT 0xff
116 /* Hardware IDs ISA PNP */
117#define HW_ID_DIVA_PRO 3 /* same as IDI_ADAPTER_DIVA */
118#define HW_ID_MAESTRA 4 /* same as IDI_ADAPTER_MAESTRA */
119#define HW_ID_PICCOLA 5
120#define HW_ID_DIVA_PRO20 6
121#define HW_ID_DIVA20 7
122#define HW_ID_DIVA_PRO20_U 8
123#define HW_ID_DIVA20_U 9
124#define HW_ID_DIVA30 10
125#define HW_ID_DIVA30_U 11
126 /* Hardware IDs PCI */
127#define HW_ID_EICON_PCI 0x1133
128#define HW_ID_SIEMENS_PCI 0x8001 /* unused SubVendor ID for Siemens Cornet-N cards */
129#define HW_ID_PROTTYPE_CORNETN 0x0014 /* SubDevice ID for Siemens Cornet-N cards */
130#define HW_ID_FUJITSU_SIEMENS_PCI 0x110A /* SubVendor ID for Fujitsu Siemens */
131#define HW_ID_GS03_PCI 0x0021 /* SubDevice ID for Fujitsu Siemens ISDN S0 card */
132#define HW_ID_DIVA_PRO20_PCI 0xe001
133#define HW_ID_DIVA20_PCI 0xe002
134#define HW_ID_DIVA_PRO20_PCI_U 0xe003
135#define HW_ID_DIVA20_PCI_U 0xe004
136#define HW_ID_DIVA201_PCI 0xe005
137#define HW_ID_DIVA_CT_ST 0xe006
138#define HW_ID_DIVA_CT_U 0xe007
139#define HW_ID_DIVA_CTL_ST 0xe008
140#define HW_ID_DIVA_CTL_U 0xe009
141#define HW_ID_DIVA_ISDN_V90_PCI 0xe00a
142#define HW_ID_DIVA202_PCI_ST 0xe00b
143#define HW_ID_DIVA202_PCI_U 0xe00c
144#define HW_ID_DIVA_PRO30_PCI 0xe00d
145#define HW_ID_MAESTRA_PCI 0xe010
146#define HW_ID_MAESTRAQ_PCI 0xe012
147#define HW_ID_DSRV_Q8M_V2_PCI 0xe013
148#define HW_ID_MAESTRAP_PCI 0xe014
149#define HW_ID_DSRV_P30M_V2_PCI 0xe015
150#define HW_ID_DSRV_VOICE_Q8M_PCI 0xe016
151#define HW_ID_DSRV_VOICE_Q8M_V2_PCI 0xe017
152#define HW_ID_DSRV_B2M_V2_PCI 0xe018
153#define HW_ID_DSRV_VOICE_P30M_V2_PCI 0xe019
154#define HW_ID_DSRV_B2F_PCI 0xe01a
155#define HW_ID_DSRV_VOICE_B2M_V2_PCI 0xe01b
156 /* Hardware IDs USB */
157#define EICON_USB_VENDOR_ID 0x071D
158#define HW_ID_DIVA_USB_REV1 0x1000
159#define HW_ID_DIVA_USB_REV2 0x1003
160#define HW_ID_TELEDAT_SURF_USB_REV2 0x1004
161#define HW_ID_TELEDAT_SURF_USB_REV1 0x2000
162/* --------------------------------------------------------------------------
163 Adapter array change notification framework
164 -------------------------------------------------------------------------- */
165typedef void (IDI_CALL_LINK_T* didd_adapter_change_callback_t)( void IDI_CALL_ENTITY_T * context, DESCRIPTOR* adapter, int removal);
166/* -------------------------------------------------------------------------- */
167#define DI_VOICE 0x0 /* obsolete define */
168#define DI_FAX3 0x1
169#define DI_MODEM 0x2
170#define DI_POST 0x4
171#define DI_V110 0x8
172#define DI_V120 0x10
173#define DI_POTS 0x20
174#define DI_CODEC 0x40
175#define DI_MANAGE 0x80
176#define DI_V_42 0x0100
177#define DI_EXTD_FAX 0x0200 /* Extended FAX (ECM, 2D, T.6, Polling) */
178#define DI_AT_PARSER 0x0400 /* Build-in AT Parser in the L2 */
179#define DI_VOICE_OVER_IP 0x0800 /* Voice over IP support */
180typedef void (IDI_CALL_LINK_T* _IDI_CALL)(void*, ENTITY*);
181#endif
diff --git a/drivers/isdn/hardware/eicon/did_vers.h b/drivers/isdn/hardware/eicon/did_vers.h
new file mode 100644
index 000000000000..538c590fdf42
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/did_vers.h
@@ -0,0 +1,26 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26static char diva_didd_common_code_build[] = "102-51";
diff --git a/drivers/isdn/hardware/eicon/diddfunc.c b/drivers/isdn/hardware/eicon/diddfunc.c
new file mode 100644
index 000000000000..3029234178d8
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/diddfunc.c
@@ -0,0 +1,115 @@
1/* $Id: diddfunc.c,v 1.14.6.2 2004/08/28 20:03:53 armin Exp $
2 *
3 * DIDD Interface module for Eicon active cards.
4 *
5 * Functions are in dadapter.c
6 *
7 * Copyright 2002-2003 by Armin Schindler (mac@melware.de)
8 * Copyright 2002-2003 Cytronics & Melware (info@melware.de)
9 *
10 * This software may be used and distributed according to the terms
11 * of the GNU General Public License, incorporated herein by reference.
12 */
13
14#include "platform.h"
15#include "di_defs.h"
16#include "dadapter.h"
17#include "divasync.h"
18
19#define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR)
20#define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG)
21
22
23extern void DIVA_DIDD_Read(void *, int);
24extern char *DRIVERRELEASE_DIDD;
25static dword notify_handle;
26static DESCRIPTOR _DAdapter;
27
28/*
29 * didd callback function
30 */
31static void *didd_callback(void *context, DESCRIPTOR * adapter,
32 int removal)
33{
34 if (adapter->type == IDI_DADAPTER) {
35 DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."))
36 return (NULL);
37 } else if (adapter->type == IDI_DIMAINT) {
38 if (removal) {
39 DbgDeregister();
40 } else {
41 DbgRegister("DIDD", DRIVERRELEASE_DIDD, DBG_DEFAULT);
42 }
43 }
44 return (NULL);
45}
46
47/*
48 * connect to didd
49 */
50static int DIVA_INIT_FUNCTION connect_didd(void)
51{
52 int x = 0;
53 int dadapter = 0;
54 IDI_SYNC_REQ req;
55 DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
56
57 DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
58
59 for (x = 0; x < MAX_DESCRIPTORS; x++) {
60 if (DIDD_Table[x].type == IDI_DADAPTER) { /* DADAPTER found */
61 dadapter = 1;
62 memcpy(&_DAdapter, &DIDD_Table[x], sizeof(_DAdapter));
63 req.didd_notify.e.Req = 0;
64 req.didd_notify.e.Rc =
65 IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
66 req.didd_notify.info.callback = (void *)didd_callback;
67 req.didd_notify.info.context = NULL;
68 _DAdapter.request((ENTITY *) & req);
69 if (req.didd_notify.e.Rc != 0xff)
70 return (0);
71 notify_handle = req.didd_notify.info.handle;
72 } else if (DIDD_Table[x].type == IDI_DIMAINT) { /* MAINT found */
73 DbgRegister("DIDD", DRIVERRELEASE_DIDD, DBG_DEFAULT);
74 }
75 }
76 return (dadapter);
77}
78
79/*
80 * disconnect from didd
81 */
82static void DIVA_EXIT_FUNCTION disconnect_didd(void)
83{
84 IDI_SYNC_REQ req;
85
86 req.didd_notify.e.Req = 0;
87 req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
88 req.didd_notify.info.handle = notify_handle;
89 _DAdapter.request((ENTITY *) & req);
90}
91
92/*
93 * init
94 */
95int DIVA_INIT_FUNCTION diddfunc_init(void)
96{
97 diva_didd_load_time_init();
98
99 if (!connect_didd()) {
100 DBG_ERR(("init: failed to connect to DIDD."))
101 diva_didd_load_time_finit();
102 return (0);
103 }
104 return (1);
105}
106
107/*
108 * finit
109 */
110void DIVA_EXIT_FUNCTION diddfunc_finit(void)
111{
112 DbgDeregister();
113 disconnect_didd();
114 diva_didd_load_time_finit();
115}
diff --git a/drivers/isdn/hardware/eicon/diva.c b/drivers/isdn/hardware/eicon/diva.c
new file mode 100644
index 000000000000..8ab8027f33c0
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/diva.c
@@ -0,0 +1,660 @@
1/* $Id: diva.c,v 1.21.4.1 2004/05/08 14:33:43 armin Exp $ */
2
3#define CARDTYPE_H_WANT_DATA 1
4#define CARDTYPE_H_WANT_IDI_DATA 0
5#define CARDTYPE_H_WANT_RESOURCE_DATA 0
6#define CARDTYPE_H_WANT_FILE_DATA 0
7
8#include "platform.h"
9#include "debuglib.h"
10#include "cardtype.h"
11#include "pc.h"
12#include "di_defs.h"
13#include "di.h"
14#include "io.h"
15#include "pc_maint.h"
16#include "xdi_msg.h"
17#include "xdi_adapter.h"
18#include "diva_pci.h"
19#include "diva.h"
20
21#ifdef CONFIG_ISDN_DIVAS_PRIPCI
22#include "os_pri.h"
23#endif
24#ifdef CONFIG_ISDN_DIVAS_BRIPCI
25#include "os_bri.h"
26#include "os_4bri.h"
27#endif
28
29PISDN_ADAPTER IoAdapters[MAX_ADAPTER];
30extern IDI_CALL Requests[MAX_ADAPTER];
31extern int create_adapter_proc(diva_os_xdi_adapter_t * a);
32extern void remove_adapter_proc(diva_os_xdi_adapter_t * a);
33
34#define DivaIdiReqFunc(N) \
35static void DivaIdiRequest##N(ENTITY *e) \
36{ if ( IoAdapters[N] ) (* IoAdapters[N]->DIRequest)(IoAdapters[N], e) ; }
37
38/*
39** Create own 32 Adapters
40*/
41DivaIdiReqFunc(0)
42DivaIdiReqFunc(1)
43DivaIdiReqFunc(2)
44DivaIdiReqFunc(3)
45DivaIdiReqFunc(4)
46DivaIdiReqFunc(5)
47DivaIdiReqFunc(6)
48DivaIdiReqFunc(7)
49DivaIdiReqFunc(8)
50DivaIdiReqFunc(9)
51DivaIdiReqFunc(10)
52DivaIdiReqFunc(11)
53DivaIdiReqFunc(12)
54DivaIdiReqFunc(13)
55DivaIdiReqFunc(14)
56DivaIdiReqFunc(15)
57DivaIdiReqFunc(16)
58DivaIdiReqFunc(17)
59DivaIdiReqFunc(18)
60DivaIdiReqFunc(19)
61DivaIdiReqFunc(20)
62DivaIdiReqFunc(21)
63DivaIdiReqFunc(22)
64DivaIdiReqFunc(23)
65DivaIdiReqFunc(24)
66DivaIdiReqFunc(25)
67DivaIdiReqFunc(26)
68DivaIdiReqFunc(27)
69DivaIdiReqFunc(28)
70DivaIdiReqFunc(29)
71DivaIdiReqFunc(30)
72DivaIdiReqFunc(31)
73
74struct pt_regs;
75
76/*
77** LOCALS
78*/
79static LIST_HEAD(adapter_queue);
80
81typedef struct _diva_get_xlog {
82 word command;
83 byte req;
84 byte rc;
85 byte data[sizeof(struct mi_pc_maint)];
86} diva_get_xlog_t;
87
88typedef struct _diva_supported_cards_info {
89 int CardOrdinal;
90 diva_init_card_proc_t init_card;
91} diva_supported_cards_info_t;
92
93static diva_supported_cards_info_t divas_supported_cards[] = {
94#ifdef CONFIG_ISDN_DIVAS_PRIPCI
95 /*
96 PRI Cards
97 */
98 {CARDTYPE_DIVASRV_P_30M_PCI, diva_pri_init_card},
99 /*
100 PRI Rev.2 Cards
101 */
102 {CARDTYPE_DIVASRV_P_30M_V2_PCI, diva_pri_init_card},
103 /*
104 PRI Rev.2 VoIP Cards
105 */
106 {CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI, diva_pri_init_card},
107#endif
108#ifdef CONFIG_ISDN_DIVAS_BRIPCI
109 /*
110 4BRI Rev 1 Cards
111 */
112 {CARDTYPE_DIVASRV_Q_8M_PCI, diva_4bri_init_card},
113 {CARDTYPE_DIVASRV_VOICE_Q_8M_PCI, diva_4bri_init_card},
114 /*
115 4BRI Rev 2 Cards
116 */
117 {CARDTYPE_DIVASRV_Q_8M_V2_PCI, diva_4bri_init_card},
118 {CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI, diva_4bri_init_card},
119 /*
120 4BRI Based BRI Rev 2 Cards
121 */
122 {CARDTYPE_DIVASRV_B_2M_V2_PCI, diva_4bri_init_card},
123 {CARDTYPE_DIVASRV_B_2F_PCI, diva_4bri_init_card},
124 {CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI, diva_4bri_init_card},
125 /*
126 BRI
127 */
128 {CARDTYPE_MAESTRA_PCI, diva_bri_init_card},
129#endif
130
131 /*
132 EOL
133 */
134 {-1}
135};
136
137static void diva_init_request_array(void);
138static void *divas_create_pci_card(int handle, void *pci_dev_handle);
139
140static diva_os_spin_lock_t adapter_lock;
141
142static int diva_find_free_adapters(int base, int nr)
143{
144 int i;
145
146 for (i = 0; i < nr; i++) {
147 if (IoAdapters[base + i]) {
148 return (-1);
149 }
150 }
151
152 return (0);
153}
154
155static diva_os_xdi_adapter_t *diva_q_get_next(struct list_head * what)
156{
157 diva_os_xdi_adapter_t *a = NULL;
158
159 if (what && (what->next != &adapter_queue))
160 a = list_entry(what->next, diva_os_xdi_adapter_t, link);
161
162 return(a);
163}
164
165/* --------------------------------------------------------------------------
166 Add card to the card list
167 -------------------------------------------------------------------------- */
168void *diva_driver_add_card(void *pdev, unsigned long CardOrdinal)
169{
170 diva_os_spin_lock_magic_t old_irql;
171 diva_os_xdi_adapter_t *pdiva, *pa;
172 int i, j, max, nr;
173
174 for (i = 0; divas_supported_cards[i].CardOrdinal != -1; i++) {
175 if (divas_supported_cards[i].CardOrdinal == CardOrdinal) {
176 if (!(pdiva = divas_create_pci_card(i, pdev))) {
177 return NULL;
178 }
179 switch (CardOrdinal) {
180 case CARDTYPE_DIVASRV_Q_8M_PCI:
181 case CARDTYPE_DIVASRV_VOICE_Q_8M_PCI:
182 case CARDTYPE_DIVASRV_Q_8M_V2_PCI:
183 case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI:
184 max = MAX_ADAPTER - 4;
185 nr = 4;
186 break;
187
188 default:
189 max = MAX_ADAPTER;
190 nr = 1;
191 }
192
193 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card");
194
195 for (i = 0; i < max; i++) {
196 if (!diva_find_free_adapters(i, nr)) {
197 pdiva->controller = i + 1;
198 pdiva->xdi_adapter.ANum = pdiva->controller;
199 IoAdapters[i] = &pdiva->xdi_adapter;
200 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
201 create_adapter_proc(pdiva); /* add adapter to proc file system */
202
203 DBG_LOG(("add %s:%d",
204 CardProperties
205 [CardOrdinal].Name,
206 pdiva->controller))
207
208 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card");
209 pa = pdiva;
210 for (j = 1; j < nr; j++) { /* slave adapters, if any */
211 pa = diva_q_get_next(&pa->link);
212 if (pa && !pa->interface.cleanup_adapter_proc) {
213 pa->controller = i + 1 + j;
214 pa->xdi_adapter.ANum = pa->controller;
215 IoAdapters[i + j] = &pa->xdi_adapter;
216 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
217 DBG_LOG(("add slave adapter (%d)",
218 pa->controller))
219 create_adapter_proc(pa); /* add adapter to proc file system */
220 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card");
221 } else {
222 DBG_ERR(("slave adapter problem"))
223 break;
224 }
225 }
226
227 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
228 return (pdiva);
229 }
230 }
231
232 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
233
234 /*
235 Not able to add adapter - remove it and return error
236 */
237 DBG_ERR(("can not alloc request array"))
238 diva_driver_remove_card(pdiva);
239
240 return NULL;
241 }
242 }
243
244 return NULL;
245}
246
247/* --------------------------------------------------------------------------
248 Called on driver load, MAIN, main, DriverEntry
249 -------------------------------------------------------------------------- */
250int divasa_xdi_driver_entry(void)
251{
252 diva_os_initialize_spin_lock(&adapter_lock, "adapter");
253 memset(&IoAdapters[0], 0x00, sizeof(IoAdapters));
254 diva_init_request_array();
255
256 return (0);
257}
258
259/* --------------------------------------------------------------------------
260 Remove adapter from list
261 -------------------------------------------------------------------------- */
262static diva_os_xdi_adapter_t *get_and_remove_from_queue(void)
263{
264 diva_os_spin_lock_magic_t old_irql;
265 diva_os_xdi_adapter_t *a = NULL;
266
267 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "driver_unload");
268
269 if (!list_empty(&adapter_queue)) {
270 a = list_entry(adapter_queue.next, diva_os_xdi_adapter_t, link);
271 list_del(adapter_queue.next);
272 }
273
274 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "driver_unload");
275 return (a);
276}
277
278/* --------------------------------------------------------------------------
279 Remove card from the card list
280 -------------------------------------------------------------------------- */
281void diva_driver_remove_card(void *pdiva)
282{
283 diva_os_spin_lock_magic_t old_irql;
284 diva_os_xdi_adapter_t *a[4];
285 diva_os_xdi_adapter_t *pa;
286 int i;
287
288 pa = a[0] = (diva_os_xdi_adapter_t *) pdiva;
289 a[1] = a[2] = a[3] = NULL;
290
291 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "remode adapter");
292
293 for (i = 1; i < 4; i++) {
294 if ((pa = diva_q_get_next(&pa->link))
295 && !pa->interface.cleanup_adapter_proc) {
296 a[i] = pa;
297 } else {
298 break;
299 }
300 }
301
302 for (i = 0; ((i < 4) && a[i]); i++) {
303 list_del(&a[i]->link);
304 }
305
306 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "driver_unload");
307
308 (*(a[0]->interface.cleanup_adapter_proc)) (a[0]);
309
310 for (i = 0; i < 4; i++) {
311 if (a[i]) {
312 if (a[i]->controller) {
313 DBG_LOG(("remove adapter (%d)",
314 a[i]->controller)) IoAdapters[a[i]->controller - 1] = NULL;
315 remove_adapter_proc(a[i]);
316 }
317 diva_os_free(0, a[i]);
318 }
319 }
320}
321
322/* --------------------------------------------------------------------------
323 Create diva PCI adapter and init internal adapter structures
324 -------------------------------------------------------------------------- */
325static void *divas_create_pci_card(int handle, void *pci_dev_handle)
326{
327 diva_supported_cards_info_t *pI = &divas_supported_cards[handle];
328 diva_os_spin_lock_magic_t old_irql;
329 diva_os_xdi_adapter_t *a;
330
331 DBG_LOG(("found %d-%s", pI->CardOrdinal, CardProperties[pI->CardOrdinal].Name))
332
333 if (!(a = (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a)))) {
334 DBG_ERR(("A: can't alloc adapter"));
335 return NULL;
336 }
337
338 memset(a, 0x00, sizeof(*a));
339
340 a->CardIndex = handle;
341 a->CardOrdinal = pI->CardOrdinal;
342 a->Bus = DIVAS_XDI_ADAPTER_BUS_PCI;
343 a->xdi_adapter.cardType = a->CardOrdinal;
344 a->resources.pci.bus = diva_os_get_pci_bus(pci_dev_handle);
345 a->resources.pci.func = diva_os_get_pci_func(pci_dev_handle);
346 a->resources.pci.hdev = pci_dev_handle;
347
348 /*
349 Add master adapter first, so slave adapters will receive higher
350 numbers as master adapter
351 */
352 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
353 list_add_tail(&a->link, &adapter_queue);
354 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
355
356 if ((*(pI->init_card)) (a)) {
357 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
358 list_del(&a->link);
359 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
360 diva_os_free(0, a);
361 DBG_ERR(("A: can't get adapter resources"));
362 return NULL;
363 }
364
365 return (a);
366}
367
368/* --------------------------------------------------------------------------
369 Called on driver unload FINIT, finit, Unload
370 -------------------------------------------------------------------------- */
371void divasa_xdi_driver_unload(void)
372{
373 diva_os_xdi_adapter_t *a;
374
375 while ((a = get_and_remove_from_queue())) {
376 if (a->interface.cleanup_adapter_proc) {
377 (*(a->interface.cleanup_adapter_proc)) (a);
378 }
379 if (a->controller) {
380 IoAdapters[a->controller - 1] = NULL;
381 remove_adapter_proc(a);
382 }
383 diva_os_free(0, a);
384 }
385 diva_os_destroy_spin_lock(&adapter_lock, "adapter");
386}
387
388/*
389** Receive and process command from user mode utility
390*/
391void *diva_xdi_open_adapter(void *os_handle, const void __user *src,
392 int length,
393 divas_xdi_copy_from_user_fn_t cp_fn)
394{
395 diva_xdi_um_cfg_cmd_t msg;
396 diva_os_xdi_adapter_t *a = NULL;
397 diva_os_spin_lock_magic_t old_irql;
398 struct list_head *tmp;
399
400 if (length < sizeof(diva_xdi_um_cfg_cmd_t)) {
401 DBG_ERR(("A: A(?) open, msg too small (%d < %d)",
402 length, sizeof(diva_xdi_um_cfg_cmd_t)))
403 return NULL;
404 }
405 if ((*cp_fn) (os_handle, &msg, src, sizeof(msg)) <= 0) {
406 DBG_ERR(("A: A(?) open, write error"))
407 return NULL;
408 }
409 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "open_adapter");
410 list_for_each(tmp, &adapter_queue) {
411 a = list_entry(tmp, diva_os_xdi_adapter_t, link);
412 if (a->controller == (int)msg.adapter)
413 break;
414 a = NULL;
415 }
416 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "open_adapter");
417
418 if (!a) {
419 DBG_ERR(("A: A(%d) open, adapter not found", msg.adapter))
420 }
421
422 return (a);
423}
424
425/*
426** Easy cleanup mailbox status
427*/
428void diva_xdi_close_adapter(void *adapter, void *os_handle)
429{
430 diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
431
432 a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
433 if (a->xdi_mbox.data) {
434 diva_os_free(0, a->xdi_mbox.data);
435 a->xdi_mbox.data = NULL;
436 }
437}
438
439int
440diva_xdi_write(void *adapter, void *os_handle, const void __user *src,
441 int length, divas_xdi_copy_from_user_fn_t cp_fn)
442{
443 diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
444 void *data;
445
446 if (a->xdi_mbox.status & DIVA_XDI_MBOX_BUSY) {
447 DBG_ERR(("A: A(%d) write, mbox busy", a->controller))
448 return (-1);
449 }
450
451 if (length < sizeof(diva_xdi_um_cfg_cmd_t)) {
452 DBG_ERR(("A: A(%d) write, message too small (%d < %d)",
453 a->controller, length,
454 sizeof(diva_xdi_um_cfg_cmd_t)))
455 return (-3);
456 }
457
458 if (!(data = diva_os_malloc(0, length))) {
459 DBG_ERR(("A: A(%d) write, ENOMEM", a->controller))
460 return (-2);
461 }
462
463 length = (*cp_fn) (os_handle, data, src, length);
464 if (length > 0) {
465 if ((*(a->interface.cmd_proc))
466 (a, (diva_xdi_um_cfg_cmd_t *) data, length)) {
467 length = -3;
468 }
469 } else {
470 DBG_ERR(("A: A(%d) write error (%d)", a->controller,
471 length))
472 }
473
474 diva_os_free(0, data);
475
476 return (length);
477}
478
479/*
480** Write answers to user mode utility, if any
481*/
482int
483diva_xdi_read(void *adapter, void *os_handle, void __user *dst,
484 int max_length, divas_xdi_copy_to_user_fn_t cp_fn)
485{
486 diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
487 int ret;
488
489 if (!(a->xdi_mbox.status & DIVA_XDI_MBOX_BUSY)) {
490 DBG_ERR(("A: A(%d) rx mbox empty", a->controller))
491 return (-1);
492 }
493 if (!a->xdi_mbox.data) {
494 a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
495 DBG_ERR(("A: A(%d) rx ENOMEM", a->controller))
496 return (-2);
497 }
498
499 if (max_length < a->xdi_mbox.data_length) {
500 DBG_ERR(("A: A(%d) rx buffer too short(%d < %d)",
501 a->controller, max_length,
502 a->xdi_mbox.data_length))
503 return (-3);
504 }
505
506 ret = (*cp_fn) (os_handle, dst, a->xdi_mbox.data,
507 a->xdi_mbox.data_length);
508 if (ret > 0) {
509 diva_os_free(0, a->xdi_mbox.data);
510 a->xdi_mbox.data = NULL;
511 a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
512 }
513
514 return (ret);
515}
516
517
518irqreturn_t diva_os_irq_wrapper(int irq, void *context, struct pt_regs *regs)
519{
520 diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) context;
521 diva_xdi_clear_interrupts_proc_t clear_int_proc;
522
523 if (!a || !a->xdi_adapter.diva_isr_handler) {
524 return IRQ_NONE;
525 }
526
527 if ((clear_int_proc = a->clear_interrupts_proc)) {
528 (*clear_int_proc) (a);
529 a->clear_interrupts_proc = NULL;
530 return IRQ_HANDLED;
531 }
532
533 (*(a->xdi_adapter.diva_isr_handler)) (&a->xdi_adapter);
534 return IRQ_HANDLED;
535}
536
537static void diva_init_request_array(void)
538{
539 Requests[0] = DivaIdiRequest0;
540 Requests[1] = DivaIdiRequest1;
541 Requests[2] = DivaIdiRequest2;
542 Requests[3] = DivaIdiRequest3;
543 Requests[4] = DivaIdiRequest4;
544 Requests[5] = DivaIdiRequest5;
545 Requests[6] = DivaIdiRequest6;
546 Requests[7] = DivaIdiRequest7;
547 Requests[8] = DivaIdiRequest8;
548 Requests[9] = DivaIdiRequest9;
549 Requests[10] = DivaIdiRequest10;
550 Requests[11] = DivaIdiRequest11;
551 Requests[12] = DivaIdiRequest12;
552 Requests[13] = DivaIdiRequest13;
553 Requests[14] = DivaIdiRequest14;
554 Requests[15] = DivaIdiRequest15;
555 Requests[16] = DivaIdiRequest16;
556 Requests[17] = DivaIdiRequest17;
557 Requests[18] = DivaIdiRequest18;
558 Requests[19] = DivaIdiRequest19;
559 Requests[20] = DivaIdiRequest20;
560 Requests[21] = DivaIdiRequest21;
561 Requests[22] = DivaIdiRequest22;
562 Requests[23] = DivaIdiRequest23;
563 Requests[24] = DivaIdiRequest24;
564 Requests[25] = DivaIdiRequest25;
565 Requests[26] = DivaIdiRequest26;
566 Requests[27] = DivaIdiRequest27;
567 Requests[28] = DivaIdiRequest28;
568 Requests[29] = DivaIdiRequest29;
569 Requests[30] = DivaIdiRequest30;
570 Requests[31] = DivaIdiRequest31;
571}
572
573void diva_xdi_display_adapter_features(int card)
574{
575 dword features;
576 if (!card || ((card - 1) >= MAX_ADAPTER) || !IoAdapters[card - 1]) {
577 return;
578 }
579 card--;
580 features = IoAdapters[card]->Properties.Features;
581
582 DBG_LOG(("FEATURES FOR ADAPTER: %d", card + 1))
583 DBG_LOG((" DI_FAX3 : %s",
584 (features & DI_FAX3) ? "Y" : "N"))
585 DBG_LOG((" DI_MODEM : %s",
586 (features & DI_MODEM) ? "Y" : "N"))
587 DBG_LOG((" DI_POST : %s",
588 (features & DI_POST) ? "Y" : "N"))
589 DBG_LOG((" DI_V110 : %s",
590 (features & DI_V110) ? "Y" : "N"))
591 DBG_LOG((" DI_V120 : %s",
592 (features & DI_V120) ? "Y" : "N"))
593 DBG_LOG((" DI_POTS : %s",
594 (features & DI_POTS) ? "Y" : "N"))
595 DBG_LOG((" DI_CODEC : %s",
596 (features & DI_CODEC) ? "Y" : "N"))
597 DBG_LOG((" DI_MANAGE : %s",
598 (features & DI_MANAGE) ? "Y" : "N"))
599 DBG_LOG((" DI_V_42 : %s",
600 (features & DI_V_42) ? "Y" : "N"))
601 DBG_LOG((" DI_EXTD_FAX : %s",
602 (features & DI_EXTD_FAX) ? "Y" : "N"))
603 DBG_LOG((" DI_AT_PARSER : %s",
604 (features & DI_AT_PARSER) ? "Y" : "N"))
605 DBG_LOG((" DI_VOICE_OVER_IP : %s",
606 (features & DI_VOICE_OVER_IP) ? "Y" : "N"))
607}
608
609void diva_add_slave_adapter(diva_os_xdi_adapter_t * a)
610{
611 diva_os_spin_lock_magic_t old_irql;
612
613 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add_slave");
614 list_add_tail(&a->link, &adapter_queue);
615 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add_slave");
616}
617
618int diva_card_read_xlog(diva_os_xdi_adapter_t * a)
619{
620 diva_get_xlog_t *req;
621 byte *data;
622
623 if (!a->xdi_adapter.Initialized || !a->xdi_adapter.DIRequest) {
624 return (-1);
625 }
626 if (!(data = diva_os_malloc(0, sizeof(struct mi_pc_maint)))) {
627 return (-1);
628 }
629 memset(data, 0x00, sizeof(struct mi_pc_maint));
630
631 if (!(req = diva_os_malloc(0, sizeof(*req)))) {
632 diva_os_free(0, data);
633 return (-1);
634 }
635 req->command = 0x0400;
636 req->req = LOG;
637 req->rc = 0x00;
638
639 (*(a->xdi_adapter.DIRequest)) (&a->xdi_adapter, (ENTITY *) req);
640
641 if (!req->rc || req->req) {
642 diva_os_free(0, data);
643 diva_os_free(0, req);
644 return (-1);
645 }
646
647 memcpy(data, &req->req, sizeof(struct mi_pc_maint));
648
649 diva_os_free(0, req);
650
651 a->xdi_mbox.data_length = sizeof(struct mi_pc_maint);
652 a->xdi_mbox.data = data;
653 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
654
655 return (0);
656}
657
658void xdiFreeFile(void *handle)
659{
660}
diff --git a/drivers/isdn/hardware/eicon/diva.h b/drivers/isdn/hardware/eicon/diva.h
new file mode 100644
index 000000000000..e979085d1b89
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/diva.h
@@ -0,0 +1,31 @@
1/* $Id: diva.h,v 1.1.2.2 2001/02/08 12:25:43 armin Exp $ */
2
3#ifndef __DIVA_XDI_OS_PART_H__
4#define __DIVA_XDI_OS_PART_H__
5
6
7int divasa_xdi_driver_entry(void);
8void divasa_xdi_driver_unload(void);
9void *diva_driver_add_card(void *pdev, unsigned long CardOrdinal);
10void diva_driver_remove_card(void *pdiva);
11
12typedef int (*divas_xdi_copy_to_user_fn_t) (void *os_handle, void __user *dst,
13 const void *src, int length);
14
15typedef int (*divas_xdi_copy_from_user_fn_t) (void *os_handle, void *dst,
16 const void __user *src, int length);
17
18int diva_xdi_read(void *adapter, void *os_handle, void __user *dst,
19 int max_length, divas_xdi_copy_to_user_fn_t cp_fn);
20
21int diva_xdi_write(void *adapter, void *os_handle, const void __user *src,
22 int length, divas_xdi_copy_from_user_fn_t cp_fn);
23
24void *diva_xdi_open_adapter(void *os_handle, const void __user *src,
25 int length,
26 divas_xdi_copy_from_user_fn_t cp_fn);
27
28void diva_xdi_close_adapter(void *adapter, void *os_handle);
29
30
31#endif
diff --git a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c
new file mode 100644
index 000000000000..7fdf8ae5be52
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/diva_didd.c
@@ -0,0 +1,151 @@
1/* $Id: diva_didd.c,v 1.13.6.4 2005/02/11 19:40:25 armin Exp $
2 *
3 * DIDD Interface module for Eicon active cards.
4 *
5 * Functions are in dadapter.c
6 *
7 * Copyright 2002-2003 by Armin Schindler (mac@melware.de)
8 * Copyright 2002-2003 Cytronics & Melware (info@melware.de)
9 *
10 * This software may be used and distributed according to the terms
11 * of the GNU General Public License, incorporated herein by reference.
12 */
13
14#include <linux/config.h>
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/kernel.h>
18#include <linux/proc_fs.h>
19
20#include "platform.h"
21#include "di_defs.h"
22#include "dadapter.h"
23#include "divasync.h"
24#include "did_vers.h"
25
26static char *main_revision = "$Revision: 1.13.6.4 $";
27
28static char *DRIVERNAME =
29 "Eicon DIVA - DIDD table (http://www.melware.net)";
30static char *DRIVERLNAME = "divadidd";
31char *DRIVERRELEASE_DIDD = "2.0";
32
33static char *main_proc_dir = "eicon";
34
35MODULE_DESCRIPTION("DIDD table driver for diva drivers");
36MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
37MODULE_SUPPORTED_DEVICE("Eicon diva drivers");
38MODULE_LICENSE("GPL");
39
40#define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR)
41#define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG)
42
43extern int diddfunc_init(void);
44extern void diddfunc_finit(void);
45
46extern void DIVA_DIDD_Read(void *, int);
47
48static struct proc_dir_entry *proc_didd;
49struct proc_dir_entry *proc_net_eicon = NULL;
50
51EXPORT_SYMBOL(DIVA_DIDD_Read);
52EXPORT_SYMBOL(proc_net_eicon);
53
54static char *getrev(const char *revision)
55{
56 char *rev;
57 char *p;
58 if ((p = strchr(revision, ':'))) {
59 rev = p + 2;
60 p = strchr(rev, '$');
61 *--p = 0;
62 } else
63 rev = "1.0";
64 return rev;
65}
66
67static int
68proc_read(char *page, char **start, off_t off, int count, int *eof,
69 void *data)
70{
71 int len = 0;
72 char tmprev[32];
73
74 strcpy(tmprev, main_revision);
75 len += sprintf(page + len, "%s\n", DRIVERNAME);
76 len += sprintf(page + len, "name : %s\n", DRIVERLNAME);
77 len += sprintf(page + len, "release : %s\n", DRIVERRELEASE_DIDD);
78 len += sprintf(page + len, "build : %s(%s)\n",
79 diva_didd_common_code_build, DIVA_BUILD);
80 len += sprintf(page + len, "revision : %s\n", getrev(tmprev));
81
82 if (off + count >= len)
83 *eof = 1;
84 if (len < off)
85 return 0;
86 *start = page + off;
87 return ((count < len - off) ? count : len - off);
88}
89
90static int DIVA_INIT_FUNCTION create_proc(void)
91{
92 proc_net_eicon = create_proc_entry(main_proc_dir, S_IFDIR, proc_net);
93
94 if (proc_net_eicon) {
95 if ((proc_didd =
96 create_proc_entry(DRIVERLNAME, S_IFREG | S_IRUGO,
97 proc_net_eicon))) {
98 proc_didd->read_proc = proc_read;
99 }
100 return (1);
101 }
102 return (0);
103}
104
105static void DIVA_EXIT_FUNCTION remove_proc(void)
106{
107 remove_proc_entry(DRIVERLNAME, proc_net_eicon);
108 remove_proc_entry(main_proc_dir, proc_net);
109}
110
111static int DIVA_INIT_FUNCTION divadidd_init(void)
112{
113 char tmprev[32];
114 int ret = 0;
115
116 printk(KERN_INFO "%s\n", DRIVERNAME);
117 printk(KERN_INFO "%s: Rel:%s Rev:", DRIVERLNAME, DRIVERRELEASE_DIDD);
118 strcpy(tmprev, main_revision);
119 printk("%s Build:%s(%s)\n", getrev(tmprev),
120 diva_didd_common_code_build, DIVA_BUILD);
121
122 if (!create_proc()) {
123 printk(KERN_ERR "%s: could not create proc entry\n",
124 DRIVERLNAME);
125 ret = -EIO;
126 goto out;
127 }
128
129 if (!diddfunc_init()) {
130 printk(KERN_ERR "%s: failed to connect to DIDD.\n",
131 DRIVERLNAME);
132#ifdef MODULE
133 remove_proc();
134#endif
135 ret = -EIO;
136 goto out;
137 }
138
139 out:
140 return (ret);
141}
142
143static void DIVA_EXIT_FUNCTION divadidd_exit(void)
144{
145 diddfunc_finit();
146 remove_proc();
147 printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
148}
149
150module_init(divadidd_init);
151module_exit(divadidd_exit);
diff --git a/drivers/isdn/hardware/eicon/diva_dma.c b/drivers/isdn/hardware/eicon/diva_dma.c
new file mode 100644
index 000000000000..f53a7407605f
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/diva_dma.c
@@ -0,0 +1,94 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#include "platform.h"
27#include "diva_dma.h"
28/*
29 Every entry has length of PAGE_SIZE
30 and represents one single physical page
31 */
32struct _diva_dma_map_entry {
33 int busy;
34 dword phys_bus_addr; /* 32bit address as seen by the card */
35 void* local_ram_addr; /* local address as seen by the host */
36 void* addr_handle; /* handle uset to free allocated memory */
37};
38/*
39 Create local mapping structure and init it to default state
40 */
41struct _diva_dma_map_entry* diva_alloc_dma_map (void* os_context, int nentries) {
42 diva_dma_map_entry_t* pmap = diva_os_malloc(0, sizeof(*pmap)*(nentries+1));
43 if (pmap)
44 memset (pmap, 0, sizeof(*pmap)*(nentries+1));
45 return pmap;
46}
47/*
48 Free local map (context should be freed before) if any
49 */
50void diva_free_dma_mapping (struct _diva_dma_map_entry* pmap) {
51 if (pmap) {
52 diva_os_free (0, pmap);
53 }
54}
55/*
56 Set information saved on the map entry
57 */
58void diva_init_dma_map_entry (struct _diva_dma_map_entry* pmap,
59 int nr, void* virt, dword phys,
60 void* addr_handle) {
61 pmap[nr].phys_bus_addr = phys;
62 pmap[nr].local_ram_addr = virt;
63 pmap[nr].addr_handle = addr_handle;
64}
65/*
66 Allocate one single entry in the map
67 */
68int diva_alloc_dma_map_entry (struct _diva_dma_map_entry* pmap) {
69 int i;
70 for (i = 0; (pmap && pmap[i].local_ram_addr); i++) {
71 if (!pmap[i].busy) {
72 pmap[i].busy = 1;
73 return (i);
74 }
75 }
76 return (-1);
77}
78/*
79 Free one single entry in the map
80 */
81void diva_free_dma_map_entry (struct _diva_dma_map_entry* pmap, int nr) {
82 pmap[nr].busy = 0;
83}
84/*
85 Get information saved on the map entry
86 */
87void diva_get_dma_map_entry (struct _diva_dma_map_entry* pmap, int nr,
88 void** pvirt, dword* pphys) {
89 *pphys = pmap[nr].phys_bus_addr;
90 *pvirt = pmap[nr].local_ram_addr;
91}
92void* diva_get_entry_handle (struct _diva_dma_map_entry* pmap, int nr) {
93 return (pmap[nr].addr_handle);
94}
diff --git a/drivers/isdn/hardware/eicon/diva_dma.h b/drivers/isdn/hardware/eicon/diva_dma.h
new file mode 100644
index 000000000000..dff80724cdbd
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/diva_dma.h
@@ -0,0 +1,48 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef __DIVA_DMA_MAPPING_IFC_H__
27#define __DIVA_DMA_MAPPING_IFC_H__
28typedef struct _diva_dma_map_entry diva_dma_map_entry_t;
29struct _diva_dma_map_entry* diva_alloc_dma_map (void* os_context, int nentries);
30void diva_init_dma_map_entry (struct _diva_dma_map_entry* pmap,
31 int nr, void* virt, dword phys,
32 void* addr_handle);
33int diva_alloc_dma_map_entry (struct _diva_dma_map_entry* pmap);
34void diva_free_dma_map_entry (struct _diva_dma_map_entry* pmap, int entry);
35void diva_get_dma_map_entry (struct _diva_dma_map_entry* pmap, int nr,
36 void** pvirt, dword* pphys);
37void diva_free_dma_mapping (struct _diva_dma_map_entry* pmap);
38/*
39 Functionality to be implemented by OS wrapper
40 and running in process context
41 */
42void diva_init_dma_map (void* hdev,
43 struct _diva_dma_map_entry** ppmap,
44 int nentries);
45void diva_free_dma_map (void* hdev,
46 struct _diva_dma_map_entry* pmap);
47void* diva_get_entry_handle (struct _diva_dma_map_entry* pmap, int nr);
48#endif
diff --git a/drivers/isdn/hardware/eicon/diva_pci.h b/drivers/isdn/hardware/eicon/diva_pci.h
new file mode 100644
index 000000000000..cc0d5102723a
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/diva_pci.h
@@ -0,0 +1,19 @@
1/* $Id: diva_pci.h,v 1.6 2003/01/04 15:29:45 schindler Exp $ */
2
3#ifndef __DIVA_PCI_INTERFACE_H__
4#define __DIVA_PCI_INTERFACE_H__
5
6void __iomem *divasa_remap_pci_bar(diva_os_xdi_adapter_t *a,
7 int id,
8 unsigned long bar,
9 unsigned long area_length);
10void divasa_unmap_pci_bar(void __iomem *bar);
11unsigned long divasa_get_pci_irq(unsigned char bus,
12 unsigned char func, void *pci_dev_handle);
13unsigned long divasa_get_pci_bar(unsigned char bus,
14 unsigned char func,
15 int bar, void *pci_dev_handle);
16byte diva_os_get_pci_bus(void *pci_dev_handle);
17byte diva_os_get_pci_func(void *pci_dev_handle);
18
19#endif
diff --git a/drivers/isdn/hardware/eicon/divacapi.h b/drivers/isdn/hardware/eicon/divacapi.h
new file mode 100644
index 000000000000..9f5b68037a26
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/divacapi.h
@@ -0,0 +1,1360 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26
27/*#define DEBUG */
28
29
30
31
32
33
34
35
36
37
38
39#define IMPLEMENT_DTMF 1
40#define IMPLEMENT_LINE_INTERCONNECT2 1
41#define IMPLEMENT_ECHO_CANCELLER 1
42#define IMPLEMENT_RTP 1
43#define IMPLEMENT_T38 1
44#define IMPLEMENT_FAX_SUB_SEP_PWD 1
45#define IMPLEMENT_V18 1
46#define IMPLEMENT_DTMF_TONE 1
47#define IMPLEMENT_PIAFS 1
48#define IMPLEMENT_FAX_PAPER_FORMATS 1
49#define IMPLEMENT_VOWN 1
50#define IMPLEMENT_CAPIDTMF 1
51#define IMPLEMENT_FAX_NONSTANDARD 1
52#define VSWITCH_SUPPORT 1
53
54
55#define IMPLEMENT_LINE_INTERCONNECT 0
56#define IMPLEMENT_MARKED_OK_AFTER_FC 1
57
58#include "capidtmf.h"
59
60/*------------------------------------------------------------------*/
61/* Common API internal definitions */
62/*------------------------------------------------------------------*/
63
64#define MAX_APPL 240
65#define MAX_NCCI 127
66
67#define MSG_IN_QUEUE_SIZE ((4096 + 3) & 0xfffc) /* must be multiple of 4 */
68
69
70#define MSG_IN_OVERHEAD sizeof(APPL *)
71
72#define MAX_NL_CHANNEL 255
73#define MAX_DATA_B3 8
74#define MAX_DATA_ACK MAX_DATA_B3
75#define MAX_MULTI_IE 6
76#define MAX_MSG_SIZE 256
77#define MAX_MSG_PARMS 10
78#define MAX_CPN_MASK_SIZE 16
79#define MAX_MSN_CONFIG 10
80#define EXT_CONTROLLER 0x80
81#define CODEC 0x01
82#define CODEC_PERMANENT 0x02
83#define ADV_VOICE 0x03
84#define MAX_CIP_TYPES 5 /* kind of CIP types for group optimization */
85#define C_IND_MASK_DWORDS ((MAX_APPL+32) >> 5)
86
87
88#define FAX_CONNECT_INFO_BUFFER_SIZE 256
89#define NCPI_BUFFER_SIZE 256
90
91#define MAX_CHANNELS_PER_PLCI 8
92#define MAX_INTERNAL_COMMAND_LEVELS 4
93#define INTERNAL_REQ_BUFFER_SIZE 272
94
95#define INTERNAL_IND_BUFFER_SIZE 768
96
97#define DTMF_PARAMETER_BUFFER_SIZE 12
98#define ADV_VOICE_COEF_BUFFER_SIZE 50
99
100#define LI_PLCI_B_QUEUE_ENTRIES 256
101
102
103
104typedef struct _APPL APPL;
105typedef struct _PLCI PLCI;
106typedef struct _NCCI NCCI;
107typedef struct _DIVA_CAPI_ADAPTER DIVA_CAPI_ADAPTER;
108typedef struct _DATA_B3_DESC DATA_B3_DESC;
109typedef struct _DATA_ACK_DESC DATA_ACK_DESC;
110typedef struct manufacturer_profile_s MANUFACTURER_PROFILE;
111typedef struct fax_ncpi_s FAX_NCPI;
112typedef struct api_parse_s API_PARSE;
113typedef struct api_save_s API_SAVE;
114typedef struct msn_config_s MSN_CONFIG;
115typedef struct msn_config_max_s MSN_CONFIG_MAX;
116typedef struct msn_ld_s MSN_LD;
117
118struct manufacturer_profile_s {
119 dword private_options;
120 dword rtp_primary_payloads;
121 dword rtp_additional_payloads;
122};
123
124struct fax_ncpi_s {
125 word options;
126 word format;
127};
128
129struct msn_config_s {
130 byte msn[MAX_CPN_MASK_SIZE];
131};
132
133struct msn_config_max_s {
134 MSN_CONFIG msn_conf[MAX_MSN_CONFIG];
135};
136
137struct msn_ld_s {
138 dword low;
139 dword high;
140};
141
142struct api_parse_s {
143 word length;
144 byte * info;
145};
146
147struct api_save_s {
148 API_PARSE parms[MAX_MSG_PARMS+1];
149 byte info[MAX_MSG_SIZE];
150};
151
152struct _DATA_B3_DESC {
153 word Handle;
154 word Number;
155 word Flags;
156 word Length;
157 void * P;
158};
159
160struct _DATA_ACK_DESC {
161 word Handle;
162 word Number;
163};
164
165typedef void (* t_std_internal_command)(dword Id, PLCI *plci, byte Rc);
166
167/************************************************************************/
168/* Don't forget to adapt dos.asm after changing the _APPL structure!!!! */
169struct _APPL {
170 word Id;
171 word NullCREnable;
172 word CDEnable;
173 dword S_Handle;
174
175
176
177
178
179
180 LIST_ENTRY s_function;
181 dword s_context;
182 word s_count;
183 APPL * s_next;
184 byte * xbuffer_used;
185 void ** xbuffer_internal;
186 void ** xbuffer_ptr;
187
188
189
190
191
192
193 byte * queue;
194 word queue_size;
195 word queue_free;
196 word queue_read;
197 word queue_write;
198 word queue_signal;
199 byte msg_lost;
200 byte appl_flags;
201 word Number;
202
203 word MaxBuffer;
204 byte MaxNCCI;
205 byte MaxNCCIData;
206 word MaxDataLength;
207 word NCCIDataFlowCtrlTimer;
208 byte * ReceiveBuffer;
209 word * DataNCCI;
210 word * DataFlags;
211};
212
213
214struct _PLCI {
215 ENTITY Sig;
216 ENTITY NL;
217 word RNum;
218 word RFlags;
219 BUFFERS RData[2];
220 BUFFERS XData[1];
221 BUFFERS NData[2];
222
223 DIVA_CAPI_ADAPTER *adapter;
224 APPL *appl;
225 PLCI *relatedPTYPLCI;
226 byte Id;
227 byte State;
228 byte sig_req;
229 byte nl_req;
230 byte SuppState;
231 byte channels;
232 byte tel;
233 byte B1_resource;
234 byte B2_prot;
235 byte B3_prot;
236
237 word command;
238 word m_command;
239 word internal_command;
240 word number;
241 word req_in_start;
242 word req_in;
243 word req_out;
244 word msg_in_write_pos;
245 word msg_in_read_pos;
246 word msg_in_wrap_pos;
247
248 void * data_sent_ptr;
249 byte data_sent;
250 byte send_disc;
251 byte sig_global_req;
252 byte sig_remove_id;
253 byte nl_global_req;
254 byte nl_remove_id;
255 byte b_channel;
256 byte adv_nl;
257 byte manufacturer;
258 byte call_dir;
259 byte hook_state;
260 byte spoofed_msg;
261 byte ptyState;
262 byte cr_enquiry;
263 word hangup_flow_ctrl_timer;
264
265 word ncci_ring_list;
266 byte inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI];
267 t_std_internal_command internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS];
268 dword c_ind_mask_table[C_IND_MASK_DWORDS];
269 dword group_optimization_mask_table[C_IND_MASK_DWORDS];
270 byte RBuffer[200];
271 dword msg_in_queue[MSG_IN_QUEUE_SIZE/sizeof(dword)];
272 API_SAVE saved_msg;
273 API_SAVE B_protocol;
274 byte fax_connect_info_length;
275 byte fax_connect_info_buffer[FAX_CONNECT_INFO_BUFFER_SIZE];
276 byte fax_edata_ack_length;
277 word nsf_control_bits;
278 byte ncpi_state;
279 byte ncpi_buffer[NCPI_BUFFER_SIZE];
280
281 byte internal_req_buffer[INTERNAL_REQ_BUFFER_SIZE];
282 byte internal_ind_buffer[INTERNAL_IND_BUFFER_SIZE + 3];
283 dword requested_options_conn;
284 dword requested_options;
285 word B1_facilities;
286 API_SAVE *adjust_b_parms_msg;
287 word adjust_b_facilities;
288 word adjust_b_command;
289 word adjust_b_ncci;
290 word adjust_b_mode;
291 word adjust_b_state;
292 byte adjust_b_restore;
293
294 byte dtmf_rec_active;
295 word dtmf_rec_pulse_ms;
296 word dtmf_rec_pause_ms;
297 byte dtmf_send_requests;
298 word dtmf_send_pulse_ms;
299 word dtmf_send_pause_ms;
300 word dtmf_cmd;
301 word dtmf_msg_number_queue[8];
302 byte dtmf_parameter_length;
303 byte dtmf_parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE];
304
305
306 t_capidtmf_state capidtmf_state;
307
308
309 byte li_bchannel_id; /* BRI: 1..2, PRI: 1..32 */
310 byte li_channel_bits;
311 byte li_notify_update;
312 word li_cmd;
313 word li_write_command;
314 word li_write_channel;
315 word li_plci_b_write_pos;
316 word li_plci_b_read_pos;
317 word li_plci_b_req_pos;
318 dword li_plci_b_queue[LI_PLCI_B_QUEUE_ENTRIES];
319
320
321 word ec_cmd;
322 word ec_idi_options;
323 word ec_tail_length;
324
325
326 byte tone_last_indication_code;
327
328 byte vswitchstate;
329 byte vsprot;
330 byte vsprotdialect;
331 byte notifiedcall; /* Flag if it is a spoofed call */
332
333 int rx_dma_descriptor;
334 dword rx_dma_magic;
335};
336
337
338struct _NCCI {
339 byte data_out;
340 byte data_pending;
341 byte data_ack_out;
342 byte data_ack_pending;
343 DATA_B3_DESC DBuffer[MAX_DATA_B3];
344 DATA_ACK_DESC DataAck[MAX_DATA_ACK];
345};
346
347
348struct _DIVA_CAPI_ADAPTER {
349 IDI_CALL request;
350 byte Id;
351 byte max_plci;
352 byte max_listen;
353 byte listen_active;
354 PLCI *plci;
355 byte ch_ncci[MAX_NL_CHANNEL+1];
356 byte ncci_ch[MAX_NCCI+1];
357 byte ncci_plci[MAX_NCCI+1];
358 byte ncci_state[MAX_NCCI+1];
359 byte ncci_next[MAX_NCCI+1];
360 NCCI ncci[MAX_NCCI+1];
361
362 byte ch_flow_control[MAX_NL_CHANNEL+1]; /* Used by XON protocol */
363 byte ch_flow_control_pending;
364 byte ch_flow_plci[MAX_NL_CHANNEL+1];
365 int last_flow_control_ch;
366
367 dword Info_Mask[MAX_APPL];
368 dword CIP_Mask[MAX_APPL];
369
370 dword Notification_Mask[MAX_APPL];
371 PLCI *codec_listen[MAX_APPL];
372 dword requested_options_table[MAX_APPL];
373 API_PROFILE profile;
374 MANUFACTURER_PROFILE man_profile;
375 dword manufacturer_features;
376
377 byte AdvCodecFLAG;
378 PLCI *AdvCodecPLCI;
379 PLCI *AdvSignalPLCI;
380 APPL *AdvSignalAppl;
381 byte TelOAD[23];
382 byte TelOSA[23];
383 byte scom_appl_disable;
384 PLCI *automatic_lawPLCI;
385 byte automatic_law;
386 byte u_law;
387
388 byte adv_voice_coef_length;
389 byte adv_voice_coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE];
390
391 byte li_pri;
392 byte li_channels;
393 word li_base;
394
395 byte adapter_disabled;
396 byte group_optimization_enabled; /* use application groups if enabled */
397 dword sdram_bar;
398 byte flag_dynamic_l1_down; /* for hunt groups:down layer 1 if no appl present*/
399 byte FlowControlIdTable[256];
400 byte FlowControlSkipTable[256];
401 void* os_card; /* pointer to associated OS dependent adapter structure */
402};
403
404
405/*------------------------------------------------------------------*/
406/* Application flags */
407/*------------------------------------------------------------------*/
408
409#define APPL_FLAG_OLD_LI_SPEC 0x01
410#define APPL_FLAG_PRIV_EC_SPEC 0x02
411
412
413/*------------------------------------------------------------------*/
414/* API parameter definitions */
415/*------------------------------------------------------------------*/
416
417#define X75_TTX 1 /* x.75 for ttx */
418#define TRF 2 /* transparent with hdlc framing */
419#define TRF_IN 3 /* transparent with hdlc fr. inc. */
420#define SDLC 4 /* sdlc, sna layer-2 */
421#define X75_BTX 5 /* x.75 for btx */
422#define LAPD 6 /* lapd (Q.921) */
423#define X25_L2 7 /* x.25 layer-2 */
424#define V120_L2 8 /* V.120 layer-2 protocol */
425#define V42_IN 9 /* V.42 layer-2 protocol, incomming */
426#define V42 10 /* V.42 layer-2 protocol */
427#define MDM_ATP 11 /* AT Parser built in the L2 */
428#define X75_V42BIS 12 /* ISO7776 (X.75 SLP) modified to support V.42 bis compression */
429#define RTPL2_IN 13 /* RTP layer-2 protocol, incomming */
430#define RTPL2 14 /* RTP layer-2 protocol */
431#define V120_V42BIS 15 /* V.120 layer-2 protocol supporting V.42 bis compression */
432
433#define T70NL 1
434#define X25PLP 2
435#define T70NLX 3
436#define TRANSPARENT_NL 4
437#define ISO8208 5
438#define T30 6
439
440
441/*------------------------------------------------------------------*/
442/* FAX interface to IDI */
443/*------------------------------------------------------------------*/
444
445#define CAPI_MAX_HEAD_LINE_SPACE 89
446#define CAPI_MAX_DATE_TIME_LENGTH 18
447
448#define T30_MAX_STATION_ID_LENGTH 20
449#define T30_MAX_SUBADDRESS_LENGTH 20
450#define T30_MAX_PASSWORD_LENGTH 20
451
452typedef struct t30_info_s T30_INFO;
453struct t30_info_s {
454 byte code;
455 byte rate_div_2400;
456 byte resolution;
457 byte data_format;
458 byte pages_low;
459 byte pages_high;
460 byte operating_mode;
461 byte control_bits_low;
462 byte control_bits_high;
463 byte feature_bits_low;
464 byte feature_bits_high;
465 byte recording_properties;
466 byte universal_6;
467 byte universal_7;
468 byte station_id_len;
469 byte head_line_len;
470 byte station_id[T30_MAX_STATION_ID_LENGTH];
471/* byte head_line[]; */
472/* byte sub_sep_length; */
473/* byte sub_sep_field[]; */
474/* byte pwd_length; */
475/* byte pwd_field[]; */
476/* byte nsf_info_length; */
477/* byte nsf_info_field[]; */
478};
479
480
481#define T30_RESOLUTION_R8_0385 0x00
482#define T30_RESOLUTION_R8_0770_OR_200 0x01
483#define T30_RESOLUTION_R8_1540 0x02
484#define T30_RESOLUTION_R16_1540_OR_400 0x04
485#define T30_RESOLUTION_R4_0385_OR_100 0x08
486#define T30_RESOLUTION_300_300 0x10
487#define T30_RESOLUTION_INCH_BASED 0x40
488#define T30_RESOLUTION_METRIC_BASED 0x80
489
490#define T30_RECORDING_WIDTH_ISO_A4 0
491#define T30_RECORDING_WIDTH_ISO_B4 1
492#define T30_RECORDING_WIDTH_ISO_A3 2
493#define T30_RECORDING_WIDTH_COUNT 3
494
495#define T30_RECORDING_LENGTH_ISO_A4 0
496#define T30_RECORDING_LENGTH_ISO_B4 1
497#define T30_RECORDING_LENGTH_UNLIMITED 2
498#define T30_RECORDING_LENGTH_COUNT 3
499
500#define T30_MIN_SCANLINE_TIME_00_00_00 0
501#define T30_MIN_SCANLINE_TIME_05_05_05 1
502#define T30_MIN_SCANLINE_TIME_10_05_05 2
503#define T30_MIN_SCANLINE_TIME_10_10_10 3
504#define T30_MIN_SCANLINE_TIME_20_10_10 4
505#define T30_MIN_SCANLINE_TIME_20_20_20 5
506#define T30_MIN_SCANLINE_TIME_40_20_20 6
507#define T30_MIN_SCANLINE_TIME_40_40_40 7
508#define T30_MIN_SCANLINE_TIME_RES_8 8
509#define T30_MIN_SCANLINE_TIME_RES_9 9
510#define T30_MIN_SCANLINE_TIME_RES_10 10
511#define T30_MIN_SCANLINE_TIME_10_10_05 11
512#define T30_MIN_SCANLINE_TIME_20_10_05 12
513#define T30_MIN_SCANLINE_TIME_20_20_10 13
514#define T30_MIN_SCANLINE_TIME_40_20_10 14
515#define T30_MIN_SCANLINE_TIME_40_40_20 15
516#define T30_MIN_SCANLINE_TIME_COUNT 16
517
518#define T30_DATA_FORMAT_SFF 0
519#define T30_DATA_FORMAT_ASCII 1
520#define T30_DATA_FORMAT_NATIVE 2
521#define T30_DATA_FORMAT_COUNT 3
522
523
524#define T30_OPERATING_MODE_STANDARD 0
525#define T30_OPERATING_MODE_CLASS2 1
526#define T30_OPERATING_MODE_CLASS1 2
527#define T30_OPERATING_MODE_CAPI 3
528#define T30_OPERATING_MODE_CAPI_NEG 4
529#define T30_OPERATING_MODE_COUNT 5
530
531 /* EDATA transmit messages */
532#define EDATA_T30_DIS 0x01
533#define EDATA_T30_FTT 0x02
534#define EDATA_T30_MCF 0x03
535#define EDATA_T30_PARAMETERS 0x04
536
537 /* EDATA receive messages */
538#define EDATA_T30_DCS 0x81
539#define EDATA_T30_TRAIN_OK 0x82
540#define EDATA_T30_EOP 0x83
541#define EDATA_T30_MPS 0x84
542#define EDATA_T30_EOM 0x85
543#define EDATA_T30_DTC 0x86
544#define EDATA_T30_PAGE_END 0x87 /* Indicates end of page data. Reserved, but not implemented ! */
545#define EDATA_T30_EOP_CAPI 0x88
546
547
548#define T30_SUCCESS 0
549#define T30_ERR_NO_DIS_RECEIVED 1
550#define T30_ERR_TIMEOUT_NO_RESPONSE 2
551#define T30_ERR_RETRY_NO_RESPONSE 3
552#define T30_ERR_TOO_MANY_REPEATS 4
553#define T30_ERR_UNEXPECTED_MESSAGE 5
554#define T30_ERR_UNEXPECTED_DCN 6
555#define T30_ERR_DTC_UNSUPPORTED 7
556#define T30_ERR_ALL_RATES_FAILED 8
557#define T30_ERR_TOO_MANY_TRAINS 9
558#define T30_ERR_RECEIVE_CORRUPTED 10
559#define T30_ERR_UNEXPECTED_DISC 11
560#define T30_ERR_APPLICATION_DISC 12
561#define T30_ERR_INCOMPATIBLE_DIS 13
562#define T30_ERR_INCOMPATIBLE_DCS 14
563#define T30_ERR_TIMEOUT_NO_COMMAND 15
564#define T30_ERR_RETRY_NO_COMMAND 16
565#define T30_ERR_TIMEOUT_COMMAND_TOO_LONG 17
566#define T30_ERR_TIMEOUT_RESPONSE_TOO_LONG 18
567#define T30_ERR_NOT_IDENTIFIED 19
568#define T30_ERR_SUPERVISORY_TIMEOUT 20
569#define T30_ERR_TOO_LONG_SCAN_LINE 21
570/* #define T30_ERR_RETRY_NO_PAGE_AFTER_MPS 22 */
571#define T30_ERR_RETRY_NO_PAGE_RECEIVED 23
572#define T30_ERR_RETRY_NO_DCS_AFTER_FTT 24
573#define T30_ERR_RETRY_NO_DCS_AFTER_EOM 25
574#define T30_ERR_RETRY_NO_DCS_AFTER_MPS 26
575#define T30_ERR_RETRY_NO_DCN_AFTER_MCF 27
576#define T30_ERR_RETRY_NO_DCN_AFTER_RTN 28
577#define T30_ERR_RETRY_NO_CFR 29
578#define T30_ERR_RETRY_NO_MCF_AFTER_EOP 30
579#define T30_ERR_RETRY_NO_MCF_AFTER_EOM 31
580#define T30_ERR_RETRY_NO_MCF_AFTER_MPS 32
581#define T30_ERR_SUB_SEP_UNSUPPORTED 33
582#define T30_ERR_PWD_UNSUPPORTED 34
583#define T30_ERR_SUB_SEP_PWD_UNSUPPORTED 35
584#define T30_ERR_INVALID_COMMAND_FRAME 36
585#define T30_ERR_UNSUPPORTED_PAGE_CODING 37
586#define T30_ERR_INVALID_PAGE_CODING 38
587#define T30_ERR_INCOMPATIBLE_PAGE_CONFIG 39
588#define T30_ERR_TIMEOUT_FROM_APPLICATION 40
589#define T30_ERR_V34FAX_NO_REACTION_ON_MARK 41
590#define T30_ERR_V34FAX_TRAINING_TIMEOUT 42
591#define T30_ERR_V34FAX_UNEXPECTED_V21 43
592#define T30_ERR_V34FAX_PRIMARY_CTS_ON 44
593#define T30_ERR_V34FAX_TURNAROUND_POLLING 45
594#define T30_ERR_V34FAX_V8_INCOMPATIBILITY 46
595
596
597#define T30_CONTROL_BIT_DISABLE_FINE 0x0001
598#define T30_CONTROL_BIT_ENABLE_ECM 0x0002
599#define T30_CONTROL_BIT_ECM_64_BYTES 0x0004
600#define T30_CONTROL_BIT_ENABLE_2D_CODING 0x0008
601#define T30_CONTROL_BIT_ENABLE_T6_CODING 0x0010
602#define T30_CONTROL_BIT_ENABLE_UNCOMPR 0x0020
603#define T30_CONTROL_BIT_ACCEPT_POLLING 0x0040
604#define T30_CONTROL_BIT_REQUEST_POLLING 0x0080
605#define T30_CONTROL_BIT_MORE_DOCUMENTS 0x0100
606#define T30_CONTROL_BIT_ACCEPT_SUBADDRESS 0x0200
607#define T30_CONTROL_BIT_ACCEPT_SEL_POLLING 0x0400
608#define T30_CONTROL_BIT_ACCEPT_PASSWORD 0x0800
609#define T30_CONTROL_BIT_ENABLE_V34FAX 0x1000
610#define T30_CONTROL_BIT_EARLY_CONNECT 0x2000
611
612#define T30_CONTROL_BIT_ALL_FEATURES (T30_CONTROL_BIT_ENABLE_ECM | T30_CONTROL_BIT_ENABLE_2D_CODING | T30_CONTROL_BIT_ENABLE_T6_CODING | T30_CONTROL_BIT_ENABLE_UNCOMPR | T30_CONTROL_BIT_ENABLE_V34FAX)
613
614#define T30_FEATURE_BIT_FINE 0x0001
615#define T30_FEATURE_BIT_ECM 0x0002
616#define T30_FEATURE_BIT_ECM_64_BYTES 0x0004
617#define T30_FEATURE_BIT_2D_CODING 0x0008
618#define T30_FEATURE_BIT_T6_CODING 0x0010
619#define T30_FEATURE_BIT_UNCOMPR_ENABLED 0x0020
620#define T30_FEATURE_BIT_POLLING 0x0040
621#define T30_FEATURE_BIT_MORE_DOCUMENTS 0x0100
622#define T30_FEATURE_BIT_V34FAX 0x1000
623
624
625#define T30_NSF_CONTROL_BIT_ENABLE_NSF 0x0001
626#define T30_NSF_CONTROL_BIT_RAW_INFO 0x0002
627#define T30_NSF_CONTROL_BIT_NEGOTIATE_IND 0x0004
628#define T30_NSF_CONTROL_BIT_NEGOTIATE_RESP 0x0008
629
630#define T30_NSF_ELEMENT_NSF_FIF 0x00
631#define T30_NSF_ELEMENT_NSC_FIF 0x01
632#define T30_NSF_ELEMENT_NSS_FIF 0x02
633#define T30_NSF_ELEMENT_COMPANY_NAME 0x03
634
635
636/*------------------------------------------------------------------*/
637/* Analog modem definitions */
638/*------------------------------------------------------------------*/
639
640typedef struct async_s ASYNC_FORMAT;
641struct async_s {
642 unsigned pe: 1;
643 unsigned parity:2;
644 unsigned spare: 2;
645 unsigned stp: 1;
646 unsigned ch_len:2; /* 3th octett in CAI */
647};
648
649
650/*------------------------------------------------------------------*/
651/* PLCI/NCCI states */
652/*------------------------------------------------------------------*/
653
654#define IDLE 0
655#define OUTG_CON_PENDING 1
656#define INC_CON_PENDING 2
657#define INC_CON_ALERT 3
658#define INC_CON_ACCEPT 4
659#define INC_ACT_PENDING 5
660#define LISTENING 6
661#define CONNECTED 7
662#define OUTG_DIS_PENDING 8
663#define INC_DIS_PENDING 9
664#define LOCAL_CONNECT 10
665#define INC_RES_PENDING 11
666#define OUTG_RES_PENDING 12
667#define SUSPENDING 13
668#define ADVANCED_VOICE_SIG 14
669#define ADVANCED_VOICE_NOSIG 15
670#define RESUMING 16
671#define INC_CON_CONNECTED_ALERT 17
672#define OUTG_REJ_PENDING 18
673
674
675/*------------------------------------------------------------------*/
676/* auxilliary states for supplementary services */
677/*------------------------------------------------------------------*/
678
679#define IDLE 0
680#define HOLD_REQUEST 1
681#define HOLD_INDICATE 2
682#define CALL_HELD 3
683#define RETRIEVE_REQUEST 4
684#define RETRIEVE_INDICATION 5
685
686/*------------------------------------------------------------------*/
687/* Capi IE + Msg types */
688/*------------------------------------------------------------------*/
689#define ESC_CAUSE 0x800|CAU /* Escape cause element */
690#define ESC_MSGTYPE 0x800|MSGTYPEIE /* Escape message type */
691#define ESC_CHI 0x800|CHI /* Escape channel id */
692#define ESC_LAW 0x800|BC /* Escape law info */
693#define ESC_CR 0x800|CRIE /* Escape CallReference */
694#define ESC_PROFILE 0x800|PROFILEIE /* Escape profile */
695#define ESC_SSEXT 0x800|SSEXTIE /* Escape Supplem. Serv.*/
696#define ESC_VSWITCH 0x800|VSWITCHIE /* Escape VSwitch */
697#define CST 0x14 /* Call State i.e. */
698#define PI 0x1E /* Progress Indicator */
699#define NI 0x27 /* Notification Ind */
700#define CONN_NR 0x4C /* Connected Number */
701#define CONG_RNR 0xBF /* Congestion RNR */
702#define CONG_RR 0xB0 /* Congestion RR */
703#define RESERVED 0xFF /* Res. for future use */
704#define ON_BOARD_CODEC 0x02 /* external controller */
705#define HANDSET 0x04 /* Codec+Handset(Pro11) */
706#define HOOK_SUPPORT 0x01 /* activate Hook signal */
707#define SCR 0x7a /* unscreened number */
708
709#define HOOK_OFF_REQ 0x9001 /* internal conn req */
710#define HOOK_ON_REQ 0x9002 /* internal disc req */
711#define SUSPEND_REQ 0x9003 /* internal susp req */
712#define RESUME_REQ 0x9004 /* internal resume req */
713#define USELAW_REQ 0x9005 /* internal law req */
714#define LISTEN_SIG_ASSIGN_PEND 0x9006
715#define PERM_LIST_REQ 0x900a /* permanent conn DCE */
716#define C_HOLD_REQ 0x9011
717#define C_RETRIEVE_REQ 0x9012
718#define C_NCR_FAC_REQ 0x9013
719#define PERM_COD_ASSIGN 0x9014
720#define PERM_COD_CALL 0x9015
721#define PERM_COD_HOOK 0x9016
722#define PERM_COD_CONN_PEND 0x9017 /* wait for connect_con */
723#define PTY_REQ_PEND 0x9018
724#define CD_REQ_PEND 0x9019
725#define CF_START_PEND 0x901a
726#define CF_STOP_PEND 0x901b
727#define ECT_REQ_PEND 0x901c
728#define GETSERV_REQ_PEND 0x901d
729#define BLOCK_PLCI 0x901e
730#define INTERR_NUMBERS_REQ_PEND 0x901f
731#define INTERR_DIVERSION_REQ_PEND 0x9020
732#define MWI_ACTIVATE_REQ_PEND 0x9021
733#define MWI_DEACTIVATE_REQ_PEND 0x9022
734#define SSEXT_REQ_COMMAND 0x9023
735#define SSEXT_NC_REQ_COMMAND 0x9024
736#define START_L1_SIG_ASSIGN_PEND 0x9025
737#define REM_L1_SIG_ASSIGN_PEND 0x9026
738#define CONF_BEGIN_REQ_PEND 0x9027
739#define CONF_ADD_REQ_PEND 0x9028
740#define CONF_SPLIT_REQ_PEND 0x9029
741#define CONF_DROP_REQ_PEND 0x902a
742#define CONF_ISOLATE_REQ_PEND 0x902b
743#define CONF_REATTACH_REQ_PEND 0x902c
744#define VSWITCH_REQ_PEND 0x902d
745#define GET_MWI_STATE 0x902e
746#define CCBS_REQUEST_REQ_PEND 0x902f
747#define CCBS_DEACTIVATE_REQ_PEND 0x9030
748#define CCBS_INTERROGATE_REQ_PEND 0x9031
749
750#define NO_INTERNAL_COMMAND 0
751#define DTMF_COMMAND_1 1
752#define DTMF_COMMAND_2 2
753#define DTMF_COMMAND_3 3
754#define MIXER_COMMAND_1 4
755#define MIXER_COMMAND_2 5
756#define MIXER_COMMAND_3 6
757#define ADV_VOICE_COMMAND_CONNECT_1 7
758#define ADV_VOICE_COMMAND_CONNECT_2 8
759#define ADV_VOICE_COMMAND_CONNECT_3 9
760#define ADV_VOICE_COMMAND_DISCONNECT_1 10
761#define ADV_VOICE_COMMAND_DISCONNECT_2 11
762#define ADV_VOICE_COMMAND_DISCONNECT_3 12
763#define ADJUST_B_RESTORE_1 13
764#define ADJUST_B_RESTORE_2 14
765#define RESET_B3_COMMAND_1 15
766#define SELECT_B_COMMAND_1 16
767#define FAX_CONNECT_INFO_COMMAND_1 17
768#define FAX_CONNECT_INFO_COMMAND_2 18
769#define FAX_ADJUST_B23_COMMAND_1 19
770#define FAX_ADJUST_B23_COMMAND_2 20
771#define EC_COMMAND_1 21
772#define EC_COMMAND_2 22
773#define EC_COMMAND_3 23
774#define RTP_CONNECT_B3_REQ_COMMAND_1 24
775#define RTP_CONNECT_B3_REQ_COMMAND_2 25
776#define RTP_CONNECT_B3_REQ_COMMAND_3 26
777#define RTP_CONNECT_B3_RES_COMMAND_1 27
778#define RTP_CONNECT_B3_RES_COMMAND_2 28
779#define RTP_CONNECT_B3_RES_COMMAND_3 29
780#define HOLD_SAVE_COMMAND_1 30
781#define RETRIEVE_RESTORE_COMMAND_1 31
782#define FAX_DISCONNECT_COMMAND_1 32
783#define FAX_DISCONNECT_COMMAND_2 33
784#define FAX_DISCONNECT_COMMAND_3 34
785#define FAX_EDATA_ACK_COMMAND_1 35
786#define FAX_EDATA_ACK_COMMAND_2 36
787#define FAX_CONNECT_ACK_COMMAND_1 37
788#define FAX_CONNECT_ACK_COMMAND_2 38
789#define STD_INTERNAL_COMMAND_COUNT 39
790
791#define UID 0x2d /* User Id for Mgmt */
792
793#define CALL_DIR_OUT 0x01 /* call direction of initial call */
794#define CALL_DIR_IN 0x02
795#define CALL_DIR_ORIGINATE 0x04 /* DTE/DCE direction according to */
796#define CALL_DIR_ANSWER 0x08 /* state of B-Channel Operation */
797#define CALL_DIR_FORCE_OUTG_NL 0x10 /* for RESET_B3 reconnect, after DISC_B3... */
798
799#define AWAITING_MANUF_CON 0x80 /* command spoofing flags */
800#define SPOOFING_REQUIRED 0xff
801#define AWAITING_SELECT_B 0xef
802
803/*------------------------------------------------------------------*/
804/* B_CTRL / DSP_CTRL */
805/*------------------------------------------------------------------*/
806
807#define DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS 0x01
808#define DSP_CTRL_SET_BCHANNEL_PASSIVATION_BRI 0x02
809#define DSP_CTRL_SET_DTMF_PARAMETERS 0x03
810
811#define MANUFACTURER_FEATURE_SLAVE_CODEC 0x00000001L
812#define MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS 0x00000002L
813#define MANUFACTURER_FEATURE_HARDDTMF 0x00000004L
814#define MANUFACTURER_FEATURE_SOFTDTMF_SEND 0x00000008L
815#define MANUFACTURER_FEATURE_DTMF_PARAMETERS 0x00000010L
816#define MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE 0x00000020L
817#define MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD 0x00000040L
818#define MANUFACTURER_FEATURE_V18 0x00000080L
819#define MANUFACTURER_FEATURE_MIXER_CH_CH 0x00000100L
820#define MANUFACTURER_FEATURE_MIXER_CH_PC 0x00000200L
821#define MANUFACTURER_FEATURE_MIXER_PC_CH 0x00000400L
822#define MANUFACTURER_FEATURE_MIXER_PC_PC 0x00000800L
823#define MANUFACTURER_FEATURE_ECHO_CANCELLER 0x00001000L
824#define MANUFACTURER_FEATURE_RTP 0x00002000L
825#define MANUFACTURER_FEATURE_T38 0x00004000L
826#define MANUFACTURER_FEATURE_TRANSP_DELIVERY_CONF 0x00008000L
827#define MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL 0x00010000L
828#define MANUFACTURER_FEATURE_OOB_CHANNEL 0x00020000L
829#define MANUFACTURER_FEATURE_IN_BAND_CHANNEL 0x00040000L
830#define MANUFACTURER_FEATURE_IN_BAND_FEATURE 0x00080000L
831#define MANUFACTURER_FEATURE_PIAFS 0x00100000L
832#define MANUFACTURER_FEATURE_DTMF_TONE 0x00200000L
833#define MANUFACTURER_FEATURE_FAX_PAPER_FORMATS 0x00400000L
834#define MANUFACTURER_FEATURE_OK_FC_LABEL 0x00800000L
835#define MANUFACTURER_FEATURE_VOWN 0x01000000L
836#define MANUFACTURER_FEATURE_XCONNECT 0x02000000L
837#define MANUFACTURER_FEATURE_DMACONNECT 0x04000000L
838#define MANUFACTURER_FEATURE_AUDIO_TAP 0x08000000L
839#define MANUFACTURER_FEATURE_FAX_NONSTANDARD 0x10000000L
840
841/*------------------------------------------------------------------*/
842/* DTMF interface to IDI */
843/*------------------------------------------------------------------*/
844
845
846#define DTMF_DIGIT_TONE_LOW_GROUP_697_HZ 0x00
847#define DTMF_DIGIT_TONE_LOW_GROUP_770_HZ 0x01
848#define DTMF_DIGIT_TONE_LOW_GROUP_852_HZ 0x02
849#define DTMF_DIGIT_TONE_LOW_GROUP_941_HZ 0x03
850#define DTMF_DIGIT_TONE_LOW_GROUP_MASK 0x03
851#define DTMF_DIGIT_TONE_HIGH_GROUP_1209_HZ 0x00
852#define DTMF_DIGIT_TONE_HIGH_GROUP_1336_HZ 0x04
853#define DTMF_DIGIT_TONE_HIGH_GROUP_1477_HZ 0x08
854#define DTMF_DIGIT_TONE_HIGH_GROUP_1633_HZ 0x0c
855#define DTMF_DIGIT_TONE_HIGH_GROUP_MASK 0x0c
856#define DTMF_DIGIT_TONE_CODE_0 0x07
857#define DTMF_DIGIT_TONE_CODE_1 0x00
858#define DTMF_DIGIT_TONE_CODE_2 0x04
859#define DTMF_DIGIT_TONE_CODE_3 0x08
860#define DTMF_DIGIT_TONE_CODE_4 0x01
861#define DTMF_DIGIT_TONE_CODE_5 0x05
862#define DTMF_DIGIT_TONE_CODE_6 0x09
863#define DTMF_DIGIT_TONE_CODE_7 0x02
864#define DTMF_DIGIT_TONE_CODE_8 0x06
865#define DTMF_DIGIT_TONE_CODE_9 0x0a
866#define DTMF_DIGIT_TONE_CODE_STAR 0x03
867#define DTMF_DIGIT_TONE_CODE_HASHMARK 0x0b
868#define DTMF_DIGIT_TONE_CODE_A 0x0c
869#define DTMF_DIGIT_TONE_CODE_B 0x0d
870#define DTMF_DIGIT_TONE_CODE_C 0x0e
871#define DTMF_DIGIT_TONE_CODE_D 0x0f
872
873#define DTMF_UDATA_REQUEST_SEND_DIGITS 16
874#define DTMF_UDATA_REQUEST_ENABLE_RECEIVER 17
875#define DTMF_UDATA_REQUEST_DISABLE_RECEIVER 18
876#define DTMF_UDATA_INDICATION_DIGITS_SENT 16
877#define DTMF_UDATA_INDICATION_DIGITS_RECEIVED 17
878#define DTMF_UDATA_INDICATION_MODEM_CALLING_TONE 18
879#define DTMF_UDATA_INDICATION_FAX_CALLING_TONE 19
880#define DTMF_UDATA_INDICATION_ANSWER_TONE 20
881
882#define UDATA_REQUEST_MIXER_TAP_DATA 27
883#define UDATA_INDICATION_MIXER_TAP_DATA 27
884
885#define DTMF_LISTEN_ACTIVE_FLAG 0x01
886#define DTMF_SEND_DIGIT_FLAG 0x01
887
888
889/*------------------------------------------------------------------*/
890/* Mixer interface to IDI */
891/*------------------------------------------------------------------*/
892
893
894#define LI2_FLAG_PCCONNECT_A_B 0x40000000
895#define LI2_FLAG_PCCONNECT_B_A 0x80000000
896
897#define MIXER_BCHANNELS_BRI 2
898#define MIXER_IC_CHANNELS_BRI MIXER_BCHANNELS_BRI
899#define MIXER_IC_CHANNEL_BASE MIXER_BCHANNELS_BRI
900#define MIXER_CHANNELS_BRI (MIXER_BCHANNELS_BRI + MIXER_IC_CHANNELS_BRI)
901#define MIXER_CHANNELS_PRI 32
902
903typedef struct li_config_s LI_CONFIG;
904
905struct xconnect_card_address_s {
906 dword low;
907 dword high;
908};
909
910struct xconnect_transfer_address_s {
911 struct xconnect_card_address_s card_address;
912 dword offset;
913};
914
915struct li_config_s {
916 DIVA_CAPI_ADAPTER *adapter;
917 PLCI *plci;
918 struct xconnect_transfer_address_s send_b;
919 struct xconnect_transfer_address_s send_pc;
920 byte *flag_table; /* dword aligned and sized */
921 byte *coef_table; /* dword aligned and sized */
922 byte channel;
923 byte curchnl;
924 byte chflags;
925};
926
927extern LI_CONFIG *li_config_table;
928extern word li_total_channels;
929
930#define LI_CHANNEL_INVOLVED 0x01
931#define LI_CHANNEL_ACTIVE 0x02
932#define LI_CHANNEL_TX_DATA 0x04
933#define LI_CHANNEL_RX_DATA 0x08
934#define LI_CHANNEL_CONFERENCE 0x10
935#define LI_CHANNEL_ADDRESSES_SET 0x80
936
937#define LI_CHFLAG_MONITOR 0x01
938#define LI_CHFLAG_MIX 0x02
939#define LI_CHFLAG_LOOP 0x04
940
941#define LI_FLAG_INTERCONNECT 0x01
942#define LI_FLAG_MONITOR 0x02
943#define LI_FLAG_MIX 0x04
944#define LI_FLAG_PCCONNECT 0x08
945#define LI_FLAG_CONFERENCE 0x10
946#define LI_FLAG_ANNOUNCEMENT 0x20
947
948#define LI_COEF_CH_CH 0x01
949#define LI_COEF_CH_PC 0x02
950#define LI_COEF_PC_CH 0x04
951#define LI_COEF_PC_PC 0x08
952#define LI_COEF_CH_CH_SET 0x10
953#define LI_COEF_CH_PC_SET 0x20
954#define LI_COEF_PC_CH_SET 0x40
955#define LI_COEF_PC_PC_SET 0x80
956
957#define LI_REQ_SILENT_UPDATE 0xffff
958
959#define LI_PLCI_B_LAST_FLAG ((dword) 0x80000000L)
960#define LI_PLCI_B_DISC_FLAG ((dword) 0x40000000L)
961#define LI_PLCI_B_SKIP_FLAG ((dword) 0x20000000L)
962#define LI_PLCI_B_FLAG_MASK ((dword) 0xe0000000L)
963
964#define UDATA_REQUEST_SET_MIXER_COEFS_BRI 24
965#define UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC 25
966#define UDATA_REQUEST_SET_MIXER_COEFS_PRI_ASYN 26
967#define UDATA_INDICATION_MIXER_COEFS_SET 24
968
969#define MIXER_FEATURE_ENABLE_TX_DATA 0x0001
970#define MIXER_FEATURE_ENABLE_RX_DATA 0x0002
971
972#define MIXER_COEF_LINE_CHANNEL_MASK 0x1f
973#define MIXER_COEF_LINE_FROM_PC_FLAG 0x20
974#define MIXER_COEF_LINE_TO_PC_FLAG 0x40
975#define MIXER_COEF_LINE_ROW_FLAG 0x80
976
977#define UDATA_REQUEST_XCONNECT_FROM 28
978#define UDATA_INDICATION_XCONNECT_FROM 28
979#define UDATA_REQUEST_XCONNECT_TO 29
980#define UDATA_INDICATION_XCONNECT_TO 29
981
982#define XCONNECT_CHANNEL_PORT_B 0x0000
983#define XCONNECT_CHANNEL_PORT_PC 0x8000
984#define XCONNECT_CHANNEL_PORT_MASK 0x8000
985#define XCONNECT_CHANNEL_NUMBER_MASK 0x7fff
986#define XCONNECT_CHANNEL_PORT_COUNT 2
987
988#define XCONNECT_SUCCESS 0x0000
989#define XCONNECT_ERROR 0x0001
990
991
992/*------------------------------------------------------------------*/
993/* Echo canceller interface to IDI */
994/*------------------------------------------------------------------*/
995
996
997#define PRIVATE_ECHO_CANCELLER 0
998
999#define PRIV_SELECTOR_ECHO_CANCELLER 255
1000
1001#define EC_ENABLE_OPERATION 1
1002#define EC_DISABLE_OPERATION 2
1003#define EC_FREEZE_COEFFICIENTS 3
1004#define EC_RESUME_COEFFICIENT_UPDATE 4
1005#define EC_RESET_COEFFICIENTS 5
1006
1007#define EC_DISABLE_NON_LINEAR_PROCESSING 0x0001
1008#define EC_DO_NOT_REQUIRE_REVERSALS 0x0002
1009#define EC_DETECT_DISABLE_TONE 0x0004
1010
1011#define EC_SUCCESS 0
1012#define EC_UNSUPPORTED_OPERATION 1
1013
1014#define EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ 1
1015#define EC_BYPASS_DUE_TO_REVERSED_2100HZ 2
1016#define EC_BYPASS_RELEASED 3
1017
1018#define DSP_CTRL_SET_LEC_PARAMETERS 0x05
1019
1020#define LEC_ENABLE_ECHO_CANCELLER 0x0001
1021#define LEC_ENABLE_2100HZ_DETECTOR 0x0002
1022#define LEC_REQUIRE_2100HZ_REVERSALS 0x0004
1023#define LEC_MANUAL_DISABLE 0x0008
1024#define LEC_ENABLE_NONLINEAR_PROCESSING 0x0010
1025#define LEC_FREEZE_COEFFICIENTS 0x0020
1026#define LEC_RESET_COEFFICIENTS 0x8000
1027
1028#define LEC_MAX_SUPPORTED_TAIL_LENGTH 32
1029
1030#define LEC_UDATA_INDICATION_DISABLE_DETECT 9
1031
1032#define LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ 0x00
1033#define LEC_DISABLE_TYPE_REVERSED_2100HZ 0x01
1034#define LEC_DISABLE_RELEASED 0x02
1035
1036
1037/*------------------------------------------------------------------*/
1038/* RTP interface to IDI */
1039/*------------------------------------------------------------------*/
1040
1041
1042#define B1_RTP 31
1043#define B2_RTP 31
1044#define B3_RTP 31
1045
1046#define PRIVATE_RTP 1
1047
1048#define RTP_PRIM_PAYLOAD_PCMU_8000 0
1049#define RTP_PRIM_PAYLOAD_1016_8000 1
1050#define RTP_PRIM_PAYLOAD_G726_32_8000 2
1051#define RTP_PRIM_PAYLOAD_GSM_8000 3
1052#define RTP_PRIM_PAYLOAD_G723_8000 4
1053#define RTP_PRIM_PAYLOAD_DVI4_8000 5
1054#define RTP_PRIM_PAYLOAD_DVI4_16000 6
1055#define RTP_PRIM_PAYLOAD_LPC_8000 7
1056#define RTP_PRIM_PAYLOAD_PCMA_8000 8
1057#define RTP_PRIM_PAYLOAD_G722_16000 9
1058#define RTP_PRIM_PAYLOAD_QCELP_8000 12
1059#define RTP_PRIM_PAYLOAD_G728_8000 14
1060#define RTP_PRIM_PAYLOAD_G729_8000 18
1061#define RTP_PRIM_PAYLOAD_GSM_HR_8000 30
1062#define RTP_PRIM_PAYLOAD_GSM_EFR_8000 31
1063
1064#define RTP_ADD_PAYLOAD_BASE 32
1065#define RTP_ADD_PAYLOAD_RED 32
1066#define RTP_ADD_PAYLOAD_CN_8000 33
1067#define RTP_ADD_PAYLOAD_DTMF 34
1068
1069#define RTP_SUCCESS 0
1070#define RTP_ERR_SSRC_OR_PAYLOAD_CHANGE 1
1071
1072#define UDATA_REQUEST_RTP_RECONFIGURE 64
1073#define UDATA_INDICATION_RTP_CHANGE 65
1074#define BUDATA_REQUEST_QUERY_RTCP_REPORT 1
1075#define BUDATA_INDICATION_RTCP_REPORT 1
1076
1077#define RTP_CONNECT_OPTION_DISC_ON_SSRC_CHANGE 0x00000001L
1078#define RTP_CONNECT_OPTION_DISC_ON_PT_CHANGE 0x00000002L
1079#define RTP_CONNECT_OPTION_DISC_ON_UNKNOWN_PT 0x00000004L
1080#define RTP_CONNECT_OPTION_NO_SILENCE_TRANSMIT 0x00010000L
1081
1082#define RTP_PAYLOAD_OPTION_VOICE_ACTIVITY_DETECT 0x0001
1083#define RTP_PAYLOAD_OPTION_DISABLE_POST_FILTER 0x0002
1084#define RTP_PAYLOAD_OPTION_G723_LOW_CODING_RATE 0x0100
1085
1086#define RTP_PACKET_FILTER_IGNORE_UNKNOWN_SSRC 0x00000001L
1087
1088#define RTP_CHANGE_FLAG_SSRC_CHANGE 0x00000001L
1089#define RTP_CHANGE_FLAG_PAYLOAD_TYPE_CHANGE 0x00000002L
1090#define RTP_CHANGE_FLAG_UNKNOWN_PAYLOAD_TYPE 0x00000004L
1091
1092
1093/*------------------------------------------------------------------*/
1094/* T.38 interface to IDI */
1095/*------------------------------------------------------------------*/
1096
1097
1098#define B1_T38 30
1099#define B2_T38 30
1100#define B3_T38 30
1101
1102#define PRIVATE_T38 2
1103
1104
1105/*------------------------------------------------------------------*/
1106/* PIAFS interface to IDI */
1107/*------------------------------------------------------------------*/
1108
1109
1110#define B1_PIAFS 29
1111#define B2_PIAFS 29
1112
1113#define PRIVATE_PIAFS 29
1114
1115/*
1116 B2 configuration for PIAFS:
1117+---------------------+------+-----------------------------------------+
1118| PIAFS Protocol | byte | Bit 1 - Protocol Speed |
1119| Speed configuration | | 0 - 32K |
1120| | | 1 - 64K (default) |
1121| | | Bit 2 - Variable Protocol Speed |
1122| | | 0 - Speed is fix |
1123| | | 1 - Speed is variable (default) |
1124+---------------------+------+-----------------------------------------+
1125| Direction | word | Enable compression/decompression for |
1126| | | 0: All direction |
1127| | | 1: disable outgoing data |
1128| | | 2: disable incomming data |
1129| | | 3: disable both direction (default) |
1130+---------------------+------+-----------------------------------------+
1131| Number of code | word | Parameter P1 of V.42bis in accordance |
1132| words | | with V.42bis |
1133+---------------------+------+-----------------------------------------+
1134| Maximum String | word | Parameter P2 of V.42bis in accordance |
1135| Length | | with V.42bis |
1136+---------------------+------+-----------------------------------------+
1137| control (UDATA) | byte | enable PIAFS control communication |
1138| abilities | | |
1139+---------------------+------+-----------------------------------------+
1140*/
1141#define PIAFS_UDATA_ABILITIES 0x80
1142
1143/*------------------------------------------------------------------*/
1144/* FAX SUB/SEP/PWD extension */
1145/*------------------------------------------------------------------*/
1146
1147
1148#define PRIVATE_FAX_SUB_SEP_PWD 3
1149
1150
1151
1152/*------------------------------------------------------------------*/
1153/* V.18 extension */
1154/*------------------------------------------------------------------*/
1155
1156
1157#define PRIVATE_V18 4
1158
1159
1160
1161/*------------------------------------------------------------------*/
1162/* DTMF TONE extension */
1163/*------------------------------------------------------------------*/
1164
1165
1166#define DTMF_GET_SUPPORTED_DETECT_CODES 0xf8
1167#define DTMF_GET_SUPPORTED_SEND_CODES 0xf9
1168#define DTMF_LISTEN_TONE_START 0xfa
1169#define DTMF_LISTEN_TONE_STOP 0xfb
1170#define DTMF_SEND_TONE 0xfc
1171#define DTMF_LISTEN_MF_START 0xfd
1172#define DTMF_LISTEN_MF_STOP 0xfe
1173#define DTMF_SEND_MF 0xff
1174
1175#define DTMF_MF_DIGIT_TONE_CODE_1 0x10
1176#define DTMF_MF_DIGIT_TONE_CODE_2 0x11
1177#define DTMF_MF_DIGIT_TONE_CODE_3 0x12
1178#define DTMF_MF_DIGIT_TONE_CODE_4 0x13
1179#define DTMF_MF_DIGIT_TONE_CODE_5 0x14
1180#define DTMF_MF_DIGIT_TONE_CODE_6 0x15
1181#define DTMF_MF_DIGIT_TONE_CODE_7 0x16
1182#define DTMF_MF_DIGIT_TONE_CODE_8 0x17
1183#define DTMF_MF_DIGIT_TONE_CODE_9 0x18
1184#define DTMF_MF_DIGIT_TONE_CODE_0 0x19
1185#define DTMF_MF_DIGIT_TONE_CODE_K1 0x1a
1186#define DTMF_MF_DIGIT_TONE_CODE_K2 0x1b
1187#define DTMF_MF_DIGIT_TONE_CODE_KP 0x1c
1188#define DTMF_MF_DIGIT_TONE_CODE_S1 0x1d
1189#define DTMF_MF_DIGIT_TONE_CODE_ST 0x1e
1190
1191#define DTMF_DIGIT_CODE_COUNT 16
1192#define DTMF_MF_DIGIT_CODE_BASE DSP_DTMF_DIGIT_CODE_COUNT
1193#define DTMF_MF_DIGIT_CODE_COUNT 15
1194#define DTMF_TOTAL_DIGIT_CODE_COUNT (DSP_MF_DIGIT_CODE_BASE + DSP_MF_DIGIT_CODE_COUNT)
1195
1196#define DTMF_TONE_DIGIT_BASE 0x80
1197
1198#define DTMF_SIGNAL_NO_TONE (DTMF_TONE_DIGIT_BASE + 0)
1199#define DTMF_SIGNAL_UNIDENTIFIED_TONE (DTMF_TONE_DIGIT_BASE + 1)
1200
1201#define DTMF_SIGNAL_DIAL_TONE (DTMF_TONE_DIGIT_BASE + 2)
1202#define DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE (DTMF_TONE_DIGIT_BASE + 3)
1203#define DTMF_SIGNAL_SPECIAL_DIAL_TONE (DTMF_TONE_DIGIT_BASE + 4) /* stutter dial tone */
1204#define DTMF_SIGNAL_SECOND_DIAL_TONE (DTMF_TONE_DIGIT_BASE + 5)
1205#define DTMF_SIGNAL_RINGING_TONE (DTMF_TONE_DIGIT_BASE + 6)
1206#define DTMF_SIGNAL_SPECIAL_RINGING_TONE (DTMF_TONE_DIGIT_BASE + 7)
1207#define DTMF_SIGNAL_BUSY_TONE (DTMF_TONE_DIGIT_BASE + 8)
1208#define DTMF_SIGNAL_CONGESTION_TONE (DTMF_TONE_DIGIT_BASE + 9) /* reorder tone */
1209#define DTMF_SIGNAL_SPECIAL_INFORMATION_TONE (DTMF_TONE_DIGIT_BASE + 10)
1210#define DTMF_SIGNAL_COMFORT_TONE (DTMF_TONE_DIGIT_BASE + 11)
1211#define DTMF_SIGNAL_HOLD_TONE (DTMF_TONE_DIGIT_BASE + 12)
1212#define DTMF_SIGNAL_RECORD_TONE (DTMF_TONE_DIGIT_BASE + 13)
1213#define DTMF_SIGNAL_CALLER_WAITING_TONE (DTMF_TONE_DIGIT_BASE + 14)
1214#define DTMF_SIGNAL_CALL_WAITING_TONE (DTMF_TONE_DIGIT_BASE + 15)
1215#define DTMF_SIGNAL_PAY_TONE (DTMF_TONE_DIGIT_BASE + 16)
1216#define DTMF_SIGNAL_POSITIVE_INDICATION_TONE (DTMF_TONE_DIGIT_BASE + 17)
1217#define DTMF_SIGNAL_NEGATIVE_INDICATION_TONE (DTMF_TONE_DIGIT_BASE + 18)
1218#define DTMF_SIGNAL_WARNING_TONE (DTMF_TONE_DIGIT_BASE + 19)
1219#define DTMF_SIGNAL_INTRUSION_TONE (DTMF_TONE_DIGIT_BASE + 20)
1220#define DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE (DTMF_TONE_DIGIT_BASE + 21)
1221#define DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE (DTMF_TONE_DIGIT_BASE + 22)
1222#define DTMF_SIGNAL_CPE_ALERTING_SIGNAL (DTMF_TONE_DIGIT_BASE + 23)
1223#define DTMF_SIGNAL_OFF_HOOK_WARNING_TONE (DTMF_TONE_DIGIT_BASE + 24)
1224
1225#define DTMF_SIGNAL_INTERCEPT_TONE (DTMF_TONE_DIGIT_BASE + 63)
1226
1227#define DTMF_SIGNAL_MODEM_CALLING_TONE (DTMF_TONE_DIGIT_BASE + 64)
1228#define DTMF_SIGNAL_FAX_CALLING_TONE (DTMF_TONE_DIGIT_BASE + 65)
1229#define DTMF_SIGNAL_ANSWER_TONE (DTMF_TONE_DIGIT_BASE + 66)
1230#define DTMF_SIGNAL_REVERSED_ANSWER_TONE (DTMF_TONE_DIGIT_BASE + 67)
1231#define DTMF_SIGNAL_ANSAM_TONE (DTMF_TONE_DIGIT_BASE + 68)
1232#define DTMF_SIGNAL_REVERSED_ANSAM_TONE (DTMF_TONE_DIGIT_BASE + 69)
1233#define DTMF_SIGNAL_BELL103_ANSWER_TONE (DTMF_TONE_DIGIT_BASE + 70)
1234#define DTMF_SIGNAL_FAX_FLAGS (DTMF_TONE_DIGIT_BASE + 71)
1235#define DTMF_SIGNAL_G2_FAX_GROUP_ID (DTMF_TONE_DIGIT_BASE + 72)
1236#define DTMF_SIGNAL_HUMAN_SPEECH (DTMF_TONE_DIGIT_BASE + 73)
1237#define DTMF_SIGNAL_ANSWERING_MACHINE_390 (DTMF_TONE_DIGIT_BASE + 74)
1238
1239#define DTMF_MF_LISTEN_ACTIVE_FLAG 0x02
1240#define DTMF_SEND_MF_FLAG 0x02
1241#define DTMF_TONE_LISTEN_ACTIVE_FLAG 0x04
1242#define DTMF_SEND_TONE_FLAG 0x04
1243
1244#define PRIVATE_DTMF_TONE 5
1245
1246
1247/*------------------------------------------------------------------*/
1248/* FAX paper format extension */
1249/*------------------------------------------------------------------*/
1250
1251
1252#define PRIVATE_FAX_PAPER_FORMATS 6
1253
1254
1255
1256/*------------------------------------------------------------------*/
1257/* V.OWN extension */
1258/*------------------------------------------------------------------*/
1259
1260
1261#define PRIVATE_VOWN 7
1262
1263
1264
1265/*------------------------------------------------------------------*/
1266/* FAX non-standard facilities extension */
1267/*------------------------------------------------------------------*/
1268
1269
1270#define PRIVATE_FAX_NONSTANDARD 8
1271
1272
1273
1274/*------------------------------------------------------------------*/
1275/* Advanced voice */
1276/*------------------------------------------------------------------*/
1277
1278#define ADV_VOICE_WRITE_ACTIVATION 0
1279#define ADV_VOICE_WRITE_DEACTIVATION 1
1280#define ADV_VOICE_WRITE_UPDATE 2
1281
1282#define ADV_VOICE_OLD_COEF_COUNT 6
1283#define ADV_VOICE_NEW_COEF_BASE (ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
1284
1285/*------------------------------------------------------------------*/
1286/* B1 resource switching */
1287/*------------------------------------------------------------------*/
1288
1289#define B1_FACILITY_LOCAL 0x01
1290#define B1_FACILITY_MIXER 0x02
1291#define B1_FACILITY_DTMFX 0x04
1292#define B1_FACILITY_DTMFR 0x08
1293#define B1_FACILITY_VOICE 0x10
1294#define B1_FACILITY_EC 0x20
1295
1296#define ADJUST_B_MODE_SAVE 0x0001
1297#define ADJUST_B_MODE_REMOVE_L23 0x0002
1298#define ADJUST_B_MODE_SWITCH_L1 0x0004
1299#define ADJUST_B_MODE_NO_RESOURCE 0x0008
1300#define ADJUST_B_MODE_ASSIGN_L23 0x0010
1301#define ADJUST_B_MODE_USER_CONNECT 0x0020
1302#define ADJUST_B_MODE_CONNECT 0x0040
1303#define ADJUST_B_MODE_RESTORE 0x0080
1304
1305#define ADJUST_B_START 0
1306#define ADJUST_B_SAVE_MIXER_1 1
1307#define ADJUST_B_SAVE_DTMF_1 2
1308#define ADJUST_B_REMOVE_L23_1 3
1309#define ADJUST_B_REMOVE_L23_2 4
1310#define ADJUST_B_SAVE_EC_1 5
1311#define ADJUST_B_SAVE_DTMF_PARAMETER_1 6
1312#define ADJUST_B_SAVE_VOICE_1 7
1313#define ADJUST_B_SWITCH_L1_1 8
1314#define ADJUST_B_SWITCH_L1_2 9
1315#define ADJUST_B_RESTORE_VOICE_1 10
1316#define ADJUST_B_RESTORE_VOICE_2 11
1317#define ADJUST_B_RESTORE_DTMF_PARAMETER_1 12
1318#define ADJUST_B_RESTORE_DTMF_PARAMETER_2 13
1319#define ADJUST_B_RESTORE_EC_1 14
1320#define ADJUST_B_RESTORE_EC_2 15
1321#define ADJUST_B_ASSIGN_L23_1 16
1322#define ADJUST_B_ASSIGN_L23_2 17
1323#define ADJUST_B_CONNECT_1 18
1324#define ADJUST_B_CONNECT_2 19
1325#define ADJUST_B_CONNECT_3 20
1326#define ADJUST_B_CONNECT_4 21
1327#define ADJUST_B_RESTORE_DTMF_1 22
1328#define ADJUST_B_RESTORE_DTMF_2 23
1329#define ADJUST_B_RESTORE_MIXER_1 24
1330#define ADJUST_B_RESTORE_MIXER_2 25
1331#define ADJUST_B_RESTORE_MIXER_3 26
1332#define ADJUST_B_RESTORE_MIXER_4 27
1333#define ADJUST_B_RESTORE_MIXER_5 28
1334#define ADJUST_B_RESTORE_MIXER_6 29
1335#define ADJUST_B_RESTORE_MIXER_7 30
1336#define ADJUST_B_END 31
1337
1338/*------------------------------------------------------------------*/
1339/* XON Protocol def's */
1340/*------------------------------------------------------------------*/
1341#define N_CH_XOFF 0x01
1342#define N_XON_SENT 0x02
1343#define N_XON_REQ 0x04
1344#define N_XON_CONNECT_IND 0x08
1345#define N_RX_FLOW_CONTROL_MASK 0x3f
1346#define N_OK_FC_PENDING 0x80
1347#define N_TX_FLOW_CONTROL_MASK 0xc0
1348
1349/*------------------------------------------------------------------*/
1350/* NCPI state */
1351/*------------------------------------------------------------------*/
1352#define NCPI_VALID_CONNECT_B3_IND 0x01
1353#define NCPI_VALID_CONNECT_B3_ACT 0x02
1354#define NCPI_VALID_DISC_B3_IND 0x04
1355#define NCPI_CONNECT_B3_ACT_SENT 0x08
1356#define NCPI_NEGOTIATE_B3_SENT 0x10
1357#define NCPI_MDM_CTS_ON_RECEIVED 0x40
1358#define NCPI_MDM_DCD_ON_RECEIVED 0x80
1359
1360/*------------------------------------------------------------------*/
diff --git a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c
new file mode 100644
index 000000000000..6146f7633be5
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/divamnt.c
@@ -0,0 +1,257 @@
1/* $Id: divamnt.c,v 1.32.6.10 2005/02/11 19:40:25 armin Exp $
2 *
3 * Driver for Eicon DIVA Server ISDN cards.
4 * Maint module
5 *
6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 */
12
13#include <linux/config.h>
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <linux/sched.h>
18#include <linux/smp_lock.h>
19#include <linux/poll.h>
20#include <linux/devfs_fs_kernel.h>
21#include <asm/uaccess.h>
22
23#include "platform.h"
24#include "di_defs.h"
25#include "divasync.h"
26#include "debug_if.h"
27
28static char *main_revision = "$Revision: 1.32.6.10 $";
29
30static int major;
31
32MODULE_DESCRIPTION("Maint driver for Eicon DIVA Server cards");
33MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
34MODULE_SUPPORTED_DEVICE("DIVA card driver");
35MODULE_LICENSE("GPL");
36
37static int buffer_length = 128;
38module_param(buffer_length, int, 0);
39static unsigned long diva_dbg_mem = 0;
40module_param(diva_dbg_mem, ulong, 0);
41
42static char *DRIVERNAME =
43 "Eicon DIVA - MAINT module (http://www.melware.net)";
44static char *DRIVERLNAME = "diva_mnt";
45static char *DEVNAME = "DivasMAINT";
46char *DRIVERRELEASE_MNT = "2.0";
47
48static wait_queue_head_t msgwaitq;
49static unsigned long opened;
50static struct timeval start_time;
51
52extern int mntfunc_init(int *, void **, unsigned long);
53extern void mntfunc_finit(void);
54extern int maint_read_write(void __user *buf, int count);
55
56/*
57 * helper functions
58 */
59static char *getrev(const char *revision)
60{
61 char *rev;
62 char *p;
63
64 if ((p = strchr(revision, ':'))) {
65 rev = p + 2;
66 p = strchr(rev, '$');
67 *--p = 0;
68 } else
69 rev = "1.0";
70
71 return rev;
72}
73
74/*
75 * kernel/user space copy functions
76 */
77int diva_os_copy_to_user(void *os_handle, void __user *dst, const void *src,
78 int length)
79{
80 return (copy_to_user(dst, src, length));
81}
82int diva_os_copy_from_user(void *os_handle, void *dst, const void __user *src,
83 int length)
84{
85 return (copy_from_user(dst, src, length));
86}
87
88/*
89 * get time
90 */
91void diva_os_get_time(dword * sec, dword * usec)
92{
93 struct timeval tv;
94
95 do_gettimeofday(&tv);
96
97 if (tv.tv_sec > start_time.tv_sec) {
98 if (start_time.tv_usec > tv.tv_usec) {
99 tv.tv_sec--;
100 tv.tv_usec += 1000000;
101 }
102 *sec = (dword) (tv.tv_sec - start_time.tv_sec);
103 *usec = (dword) (tv.tv_usec - start_time.tv_usec);
104 } else if (tv.tv_sec == start_time.tv_sec) {
105 *sec = 0;
106 if (start_time.tv_usec < tv.tv_usec) {
107 *usec = (dword) (tv.tv_usec - start_time.tv_usec);
108 } else {
109 *usec = 0;
110 }
111 } else {
112 *sec = (dword) tv.tv_sec;
113 *usec = (dword) tv.tv_usec;
114 }
115}
116
117/*
118 * device node operations
119 */
120static unsigned int maint_poll(struct file *file, poll_table * wait)
121{
122 unsigned int mask = 0;
123
124 poll_wait(file, &msgwaitq, wait);
125 mask = POLLOUT | POLLWRNORM;
126 if (file->private_data || diva_dbg_q_length()) {
127 mask |= POLLIN | POLLRDNORM;
128 }
129 return (mask);
130}
131
132static int maint_open(struct inode *ino, struct file *filep)
133{
134 /* only one open is allowed, so we test
135 it atomically */
136 if (test_and_set_bit(0, &opened))
137 return (-EBUSY);
138
139 filep->private_data = NULL;
140
141 return nonseekable_open(ino, filep);
142}
143
144static int maint_close(struct inode *ino, struct file *filep)
145{
146 if (filep->private_data) {
147 diva_os_free(0, filep->private_data);
148 filep->private_data = NULL;
149 }
150
151 /* clear 'used' flag */
152 clear_bit(0, &opened);
153
154 return (0);
155}
156
157static ssize_t divas_maint_write(struct file *file, const char __user *buf,
158 size_t count, loff_t * ppos)
159{
160 return (maint_read_write((char __user *) buf, (int) count));
161}
162
163static ssize_t divas_maint_read(struct file *file, char __user *buf,
164 size_t count, loff_t * ppos)
165{
166 return (maint_read_write(buf, (int) count));
167}
168
169static struct file_operations divas_maint_fops = {
170 .owner = THIS_MODULE,
171 .llseek = no_llseek,
172 .read = divas_maint_read,
173 .write = divas_maint_write,
174 .poll = maint_poll,
175 .open = maint_open,
176 .release = maint_close
177};
178
179static void divas_maint_unregister_chrdev(void)
180{
181 devfs_remove(DEVNAME);
182 unregister_chrdev(major, DEVNAME);
183}
184
185static int DIVA_INIT_FUNCTION divas_maint_register_chrdev(void)
186{
187 if ((major = register_chrdev(0, DEVNAME, &divas_maint_fops)) < 0)
188 {
189 printk(KERN_ERR "%s: failed to create /dev entry.\n",
190 DRIVERLNAME);
191 return (0);
192 }
193 devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, DEVNAME);
194
195 return (1);
196}
197
198/*
199 * wake up reader
200 */
201void diva_maint_wakeup_read(void)
202{
203 wake_up_interruptible(&msgwaitq);
204}
205
206/*
207 * Driver Load
208 */
209static int DIVA_INIT_FUNCTION maint_init(void)
210{
211 char tmprev[50];
212 int ret = 0;
213 void *buffer = NULL;
214
215 do_gettimeofday(&start_time);
216 init_waitqueue_head(&msgwaitq);
217
218 printk(KERN_INFO "%s\n", DRIVERNAME);
219 printk(KERN_INFO "%s: Rel:%s Rev:", DRIVERLNAME, DRIVERRELEASE_MNT);
220 strcpy(tmprev, main_revision);
221 printk("%s Build: %s \n", getrev(tmprev), DIVA_BUILD);
222
223 if (!divas_maint_register_chrdev()) {
224 ret = -EIO;
225 goto out;
226 }
227
228 if (!(mntfunc_init(&buffer_length, &buffer, diva_dbg_mem))) {
229 printk(KERN_ERR "%s: failed to connect to DIDD.\n",
230 DRIVERLNAME);
231 divas_maint_unregister_chrdev();
232 ret = -EIO;
233 goto out;
234 }
235
236 printk(KERN_INFO "%s: trace buffer = %p - %d kBytes, %s (Major: %d)\n",
237 DRIVERLNAME, buffer, (buffer_length / 1024),
238 (diva_dbg_mem == 0) ? "internal" : "external", major);
239
240 out:
241 return (ret);
242}
243
244/*
245** Driver Unload
246*/
247static void DIVA_EXIT_FUNCTION maint_exit(void)
248{
249 divas_maint_unregister_chrdev();
250 mntfunc_finit();
251
252 printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
253}
254
255module_init(maint_init);
256module_exit(maint_exit);
257
diff --git a/drivers/isdn/hardware/eicon/divasfunc.c b/drivers/isdn/hardware/eicon/divasfunc.c
new file mode 100644
index 000000000000..df61e510a28b
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/divasfunc.c
@@ -0,0 +1,238 @@
1/* $Id: divasfunc.c,v 1.23.4.2 2004/08/28 20:03:53 armin Exp $
2 *
3 * Low level driver for Eicon DIVA Server ISDN cards.
4 *
5 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
6 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
7 *
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
10 */
11
12#include "platform.h"
13#include "di_defs.h"
14#include "pc.h"
15#include "di.h"
16#include "io.h"
17#include "divasync.h"
18#include "diva.h"
19#include "xdi_vers.h"
20
21#define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR)
22#define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG)
23
24static int debugmask;
25
26extern void DIVA_DIDD_Read(void *, int);
27
28extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER];
29
30extern char *DRIVERRELEASE_DIVAS;
31
32static dword notify_handle;
33static DESCRIPTOR DAdapter;
34static DESCRIPTOR MAdapter;
35
36/* --------------------------------------------------------------------------
37 MAINT driver connector section
38 -------------------------------------------------------------------------- */
39static void no_printf(unsigned char *x, ...)
40{
41 /* dummy debug function */
42}
43
44#include "debuglib.c"
45
46/*
47 * get the adapters serial number
48 */
49void diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf)
50{
51 int contr = 0;
52
53 if ((contr = ((IoAdapter->serialNo & 0xff000000) >> 24))) {
54 sprintf(buf, "%d-%d",
55 IoAdapter->serialNo & 0x00ffffff, contr + 1);
56 } else {
57 sprintf(buf, "%d", IoAdapter->serialNo);
58 }
59}
60
61/*
62 * register a new adapter
63 */
64void diva_xdi_didd_register_adapter(int card)
65{
66 DESCRIPTOR d;
67 IDI_SYNC_REQ req;
68
69 if (card && ((card - 1) < MAX_ADAPTER) &&
70 IoAdapters[card - 1] && Requests[card - 1]) {
71 d.type = IoAdapters[card - 1]->Properties.DescType;
72 d.request = Requests[card - 1];
73 d.channels = IoAdapters[card - 1]->Properties.Channels;
74 d.features = IoAdapters[card - 1]->Properties.Features;
75 DBG_TRC(("DIDD register A(%d) channels=%d", card,
76 d.channels))
77 /* workaround for different Name in structure */
78 strlcpy(IoAdapters[card - 1]->Name,
79 IoAdapters[card - 1]->Properties.Name,
80 sizeof(IoAdapters[card - 1]->Name));
81 req.didd_remove_adapter.e.Req = 0;
82 req.didd_add_adapter.e.Rc = IDI_SYNC_REQ_DIDD_ADD_ADAPTER;
83 req.didd_add_adapter.info.descriptor = (void *) &d;
84 DAdapter.request((ENTITY *) & req);
85 if (req.didd_add_adapter.e.Rc != 0xff) {
86 DBG_ERR(("DIDD register A(%d) failed !", card))
87 }
88 IoAdapters[card - 1]->os_trap_nfy_Fnc = NULL;
89 }
90}
91
92/*
93 * remove an adapter
94 */
95void diva_xdi_didd_remove_adapter(int card)
96{
97 IDI_SYNC_REQ req;
98 ADAPTER *a = &IoAdapters[card - 1]->a;
99
100 IoAdapters[card - 1]->os_trap_nfy_Fnc = NULL;
101 DBG_TRC(("DIDD de-register A(%d)", card))
102 req.didd_remove_adapter.e.Req = 0;
103 req.didd_remove_adapter.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER;
104 req.didd_remove_adapter.info.p_request =
105 (IDI_CALL) Requests[card - 1];
106 DAdapter.request((ENTITY *) & req);
107 memset(&(a->IdTable), 0x00, 256);
108}
109
110/*
111 * start debug
112 */
113static void start_dbg(void)
114{
115 DbgRegister("DIVAS", DRIVERRELEASE_DIVAS, (debugmask) ? debugmask : DBG_DEFAULT);
116 DBG_LOG(("DIVA ISDNXDI BUILD (%s[%s]-%s-%s)",
117 DIVA_BUILD, diva_xdi_common_code_build, __DATE__,
118 __TIME__))
119}
120
121/*
122 * stop debug
123 */
124static void stop_dbg(void)
125{
126 DbgDeregister();
127 memset(&MAdapter, 0, sizeof(MAdapter));
128 dprintf = no_printf;
129}
130
131/*
132 * didd callback function
133 */
134static void *didd_callback(void *context, DESCRIPTOR * adapter,
135 int removal)
136{
137 if (adapter->type == IDI_DADAPTER) {
138 DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."));
139 return (NULL);
140 }
141
142 if (adapter->type == IDI_DIMAINT) {
143 if (removal) {
144 stop_dbg();
145 } else {
146 memcpy(&MAdapter, adapter, sizeof(MAdapter));
147 dprintf = (DIVA_DI_PRINTF) MAdapter.request;
148 start_dbg();
149 }
150 }
151 return (NULL);
152}
153
154/*
155 * connect to didd
156 */
157static int DIVA_INIT_FUNCTION connect_didd(void)
158{
159 int x = 0;
160 int dadapter = 0;
161 IDI_SYNC_REQ req;
162 DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
163
164 DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
165
166 for (x = 0; x < MAX_DESCRIPTORS; x++) {
167 if (DIDD_Table[x].type == IDI_DADAPTER) { /* DADAPTER found */
168 dadapter = 1;
169 memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
170 req.didd_notify.e.Req = 0;
171 req.didd_notify.e.Rc =
172 IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
173 req.didd_notify.info.callback = (void *)didd_callback;
174 req.didd_notify.info.context = NULL;
175 DAdapter.request((ENTITY *) & req);
176 if (req.didd_notify.e.Rc != 0xff) {
177 stop_dbg();
178 return (0);
179 }
180 notify_handle = req.didd_notify.info.handle;
181 } else if (DIDD_Table[x].type == IDI_DIMAINT) { /* MAINT found */
182 memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter));
183 dprintf = (DIVA_DI_PRINTF) MAdapter.request;
184 start_dbg();
185 }
186 }
187
188 if (!dadapter) {
189 stop_dbg();
190 }
191
192 return (dadapter);
193}
194
195/*
196 * disconnect from didd
197 */
198static void DIVA_EXIT_FUNCTION disconnect_didd(void)
199{
200 IDI_SYNC_REQ req;
201
202 stop_dbg();
203
204 req.didd_notify.e.Req = 0;
205 req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
206 req.didd_notify.info.handle = notify_handle;
207 DAdapter.request((ENTITY *) & req);
208}
209
210/*
211 * init
212 */
213int DIVA_INIT_FUNCTION divasfunc_init(int dbgmask)
214{
215 char *version;
216
217 debugmask = dbgmask;
218
219 if (!connect_didd()) {
220 DBG_ERR(("divasfunc: failed to connect to DIDD."))
221 return (0);
222 }
223
224 version = diva_xdi_common_code_build;
225
226 divasa_xdi_driver_entry();
227
228 return (1);
229}
230
231/*
232 * exit
233 */
234void DIVA_EXIT_FUNCTION divasfunc_exit(void)
235{
236 divasa_xdi_driver_unload();
237 disconnect_didd();
238}
diff --git a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c
new file mode 100644
index 000000000000..df715b47e2b4
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/divasi.c
@@ -0,0 +1,581 @@
1/* $Id: divasi.c,v 1.25.6.2 2005/01/31 12:22:20 armin Exp $
2 *
3 * Driver for Eicon DIVA Server ISDN cards.
4 * User Mode IDI Interface
5 *
6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 */
12
13#include <linux/config.h>
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <linux/sched.h>
18#include <linux/smp_lock.h>
19#include <linux/poll.h>
20#include <linux/proc_fs.h>
21#include <linux/skbuff.h>
22#include <linux/devfs_fs_kernel.h>
23#include <asm/uaccess.h>
24
25#include "platform.h"
26#include "di_defs.h"
27#include "divasync.h"
28#include "um_xdi.h"
29#include "um_idi.h"
30
31static char *main_revision = "$Revision: 1.25.6.2 $";
32
33static int major;
34
35MODULE_DESCRIPTION("User IDI Interface for Eicon ISDN cards");
36MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
37MODULE_SUPPORTED_DEVICE("DIVA card driver");
38MODULE_LICENSE("GPL");
39
40typedef struct _diva_um_idi_os_context {
41 wait_queue_head_t read_wait;
42 wait_queue_head_t close_wait;
43 struct timer_list diva_timer_id;
44 int aborted;
45 int adapter_nr;
46} diva_um_idi_os_context_t;
47
48static char *DRIVERNAME = "Eicon DIVA - User IDI (http://www.melware.net)";
49static char *DRIVERLNAME = "diva_idi";
50static char *DEVNAME = "DivasIDI";
51char *DRIVERRELEASE_IDI = "2.0";
52
53extern int idifunc_init(void);
54extern void idifunc_finit(void);
55
56/*
57 * helper functions
58 */
59static char *getrev(const char *revision)
60{
61 char *rev;
62 char *p;
63 if ((p = strchr(revision, ':'))) {
64 rev = p + 2;
65 p = strchr(rev, '$');
66 *--p = 0;
67 } else
68 rev = "1.0";
69 return rev;
70}
71
72/*
73 * LOCALS
74 */
75static ssize_t um_idi_read(struct file *file, char __user *buf, size_t count,
76 loff_t * offset);
77static ssize_t um_idi_write(struct file *file, const char __user *buf,
78 size_t count, loff_t * offset);
79static unsigned int um_idi_poll(struct file *file, poll_table * wait);
80static int um_idi_open(struct inode *inode, struct file *file);
81static int um_idi_release(struct inode *inode, struct file *file);
82static int remove_entity(void *entity);
83static void diva_um_timer_function(unsigned long data);
84
85/*
86 * proc entry
87 */
88extern struct proc_dir_entry *proc_net_eicon;
89static struct proc_dir_entry *um_idi_proc_entry = NULL;
90
91static int
92um_idi_proc_read(char *page, char **start, off_t off, int count, int *eof,
93 void *data)
94{
95 int len = 0;
96 char tmprev[32];
97
98 len += sprintf(page + len, "%s\n", DRIVERNAME);
99 len += sprintf(page + len, "name : %s\n", DRIVERLNAME);
100 len += sprintf(page + len, "release : %s\n", DRIVERRELEASE_IDI);
101 strcpy(tmprev, main_revision);
102 len += sprintf(page + len, "revision : %s\n", getrev(tmprev));
103 len += sprintf(page + len, "build : %s\n", DIVA_BUILD);
104 len += sprintf(page + len, "major : %d\n", major);
105
106 if (off + count >= len)
107 *eof = 1;
108 if (len < off)
109 return 0;
110 *start = page + off;
111 return ((count < len - off) ? count : len - off);
112}
113
114static int DIVA_INIT_FUNCTION create_um_idi_proc(void)
115{
116 um_idi_proc_entry = create_proc_entry(DRIVERLNAME,
117 S_IFREG | S_IRUGO | S_IWUSR,
118 proc_net_eicon);
119 if (!um_idi_proc_entry)
120 return (0);
121
122 um_idi_proc_entry->read_proc = um_idi_proc_read;
123 um_idi_proc_entry->owner = THIS_MODULE;
124
125 return (1);
126}
127
128static void remove_um_idi_proc(void)
129{
130 if (um_idi_proc_entry) {
131 remove_proc_entry(DRIVERLNAME, proc_net_eicon);
132 um_idi_proc_entry = NULL;
133 }
134}
135
136static struct file_operations divas_idi_fops = {
137 .owner = THIS_MODULE,
138 .llseek = no_llseek,
139 .read = um_idi_read,
140 .write = um_idi_write,
141 .poll = um_idi_poll,
142 .open = um_idi_open,
143 .release = um_idi_release
144};
145
146static void divas_idi_unregister_chrdev(void)
147{
148 devfs_remove(DEVNAME);
149 unregister_chrdev(major, DEVNAME);
150}
151
152static int DIVA_INIT_FUNCTION divas_idi_register_chrdev(void)
153{
154 if ((major = register_chrdev(0, DEVNAME, &divas_idi_fops)) < 0)
155 {
156 printk(KERN_ERR "%s: failed to create /dev entry.\n",
157 DRIVERLNAME);
158 return (0);
159 }
160 devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, DEVNAME);
161
162 return (1);
163}
164
165/*
166** Driver Load
167*/
168static int DIVA_INIT_FUNCTION divasi_init(void)
169{
170 char tmprev[50];
171 int ret = 0;
172
173 printk(KERN_INFO "%s\n", DRIVERNAME);
174 printk(KERN_INFO "%s: Rel:%s Rev:", DRIVERLNAME, DRIVERRELEASE_IDI);
175 strcpy(tmprev, main_revision);
176 printk("%s Build: %s\n", getrev(tmprev), DIVA_BUILD);
177
178 if (!divas_idi_register_chrdev()) {
179 ret = -EIO;
180 goto out;
181 }
182
183 if (!create_um_idi_proc()) {
184 divas_idi_unregister_chrdev();
185 printk(KERN_ERR "%s: failed to create proc entry.\n",
186 DRIVERLNAME);
187 ret = -EIO;
188 goto out;
189 }
190
191 if (!(idifunc_init())) {
192 remove_um_idi_proc();
193 divas_idi_unregister_chrdev();
194 printk(KERN_ERR "%s: failed to connect to DIDD.\n",
195 DRIVERLNAME);
196 ret = -EIO;
197 goto out;
198 }
199 printk(KERN_INFO "%s: started with major %d\n", DRIVERLNAME, major);
200
201 out:
202 return (ret);
203}
204
205
206/*
207** Driver Unload
208*/
209static void DIVA_EXIT_FUNCTION divasi_exit(void)
210{
211 idifunc_finit();
212 remove_um_idi_proc();
213 divas_idi_unregister_chrdev();
214
215 printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
216}
217
218module_init(divasi_init);
219module_exit(divasi_exit);
220
221
222/*
223 * FILE OPERATIONS
224 */
225
226static int
227divas_um_idi_copy_to_user(void *os_handle, void *dst, const void *src,
228 int length)
229{
230 memcpy(dst, src, length);
231 return (length);
232}
233
234static ssize_t
235um_idi_read(struct file *file, char __user *buf, size_t count, loff_t * offset)
236{
237 diva_um_idi_os_context_t *p_os;
238 int ret = -EINVAL;
239 void *data;
240
241 if (!file->private_data) {
242 return (-ENODEV);
243 }
244
245 if (!
246 (p_os =
247 (diva_um_idi_os_context_t *) diva_um_id_get_os_context(file->
248 private_data)))
249 {
250 return (-ENODEV);
251 }
252 if (p_os->aborted) {
253 return (-ENODEV);
254 }
255
256 if (!(data = diva_os_malloc(0, count))) {
257 return (-ENOMEM);
258 }
259
260 ret = diva_um_idi_read(file->private_data,
261 file, data, count,
262 divas_um_idi_copy_to_user);
263 switch (ret) {
264 case 0: /* no message available */
265 ret = (-EAGAIN);
266 break;
267 case (-1): /* adapter was removed */
268 ret = (-ENODEV);
269 break;
270 case (-2): /* message_length > length of user buffer */
271 ret = (-EFAULT);
272 break;
273 }
274
275 if (ret > 0) {
276 if (copy_to_user(buf, data, ret)) {
277 ret = (-EFAULT);
278 }
279 }
280
281 diva_os_free(0, data);
282 DBG_TRC(("read: ret %d", ret));
283 return (ret);
284}
285
286
287static int
288divas_um_idi_copy_from_user(void *os_handle, void *dst, const void *src,
289 int length)
290{
291 memcpy(dst, src, length);
292 return (length);
293}
294
295static int um_idi_open_adapter(struct file *file, int adapter_nr)
296{
297 diva_um_idi_os_context_t *p_os;
298 void *e =
299 divas_um_idi_create_entity((dword) adapter_nr, (void *) file);
300
301 if (!(file->private_data = e)) {
302 return (0);
303 }
304 p_os = (diva_um_idi_os_context_t *) diva_um_id_get_os_context(e);
305 init_waitqueue_head(&p_os->read_wait);
306 init_waitqueue_head(&p_os->close_wait);
307 init_timer(&p_os->diva_timer_id);
308 p_os->diva_timer_id.function = (void *) diva_um_timer_function;
309 p_os->diva_timer_id.data = (unsigned long) p_os;
310 p_os->aborted = 0;
311 p_os->adapter_nr = adapter_nr;
312 return (1);
313}
314
315static ssize_t
316um_idi_write(struct file *file, const char __user *buf, size_t count,
317 loff_t * offset)
318{
319 diva_um_idi_os_context_t *p_os;
320 int ret = -EINVAL;
321 void *data;
322 int adapter_nr = 0;
323
324 if (!file->private_data) {
325 /* the first write() selects the adapter_nr */
326 if (count == sizeof(int)) {
327 if (copy_from_user
328 ((void *) &adapter_nr, buf,
329 count)) return (-EFAULT);
330 if (!(um_idi_open_adapter(file, adapter_nr)))
331 return (-ENODEV);
332 return (count);
333 } else
334 return (-ENODEV);
335 }
336
337 if (!(p_os =
338 (diva_um_idi_os_context_t *) diva_um_id_get_os_context(file->
339 private_data)))
340 {
341 return (-ENODEV);
342 }
343 if (p_os->aborted) {
344 return (-ENODEV);
345 }
346
347 if (!(data = diva_os_malloc(0, count))) {
348 return (-ENOMEM);
349 }
350
351 if (copy_from_user(data, buf, count)) {
352 ret = -EFAULT;
353 } else {
354 ret = diva_um_idi_write(file->private_data,
355 file, data, count,
356 divas_um_idi_copy_from_user);
357 switch (ret) {
358 case 0: /* no space available */
359 ret = (-EAGAIN);
360 break;
361 case (-1): /* adapter was removed */
362 ret = (-ENODEV);
363 break;
364 case (-2): /* length of user buffer > max message_length */
365 ret = (-EFAULT);
366 break;
367 }
368 }
369 diva_os_free(0, data);
370 DBG_TRC(("write: ret %d", ret));
371 return (ret);
372}
373
374static unsigned int um_idi_poll(struct file *file, poll_table * wait)
375{
376 diva_um_idi_os_context_t *p_os;
377
378 if (!file->private_data) {
379 return (POLLERR);
380 }
381
382 if ((!(p_os =
383 (diva_um_idi_os_context_t *)
384 diva_um_id_get_os_context(file->private_data)))
385 || p_os->aborted) {
386 return (POLLERR);
387 }
388
389 poll_wait(file, &p_os->read_wait, wait);
390
391 if (p_os->aborted) {
392 return (POLLERR);
393 }
394
395 switch (diva_user_mode_idi_ind_ready(file->private_data, file)) {
396 case (-1):
397 return (POLLERR);
398
399 case 0:
400 return (0);
401 }
402
403 return (POLLIN | POLLRDNORM);
404}
405
406static int um_idi_open(struct inode *inode, struct file *file)
407{
408 return (0);
409}
410
411
412static int um_idi_release(struct inode *inode, struct file *file)
413{
414 diva_um_idi_os_context_t *p_os;
415 unsigned int adapter_nr;
416 int ret = 0;
417
418 if (!(file->private_data)) {
419 ret = -ENODEV;
420 goto out;
421 }
422
423 if (!(p_os =
424 (diva_um_idi_os_context_t *) diva_um_id_get_os_context(file->private_data))) {
425 ret = -ENODEV;
426 goto out;
427 }
428
429 adapter_nr = p_os->adapter_nr;
430
431 if ((ret = remove_entity(file->private_data))) {
432 goto out;
433 }
434
435 if (divas_um_idi_delete_entity
436 ((int) adapter_nr, file->private_data)) {
437 ret = -ENODEV;
438 goto out;
439 }
440
441 out:
442 return (ret);
443}
444
445int diva_os_get_context_size(void)
446{
447 return (sizeof(diva_um_idi_os_context_t));
448}
449
450void diva_os_wakeup_read(void *os_context)
451{
452 diva_um_idi_os_context_t *p_os =
453 (diva_um_idi_os_context_t *) os_context;
454 wake_up_interruptible(&p_os->read_wait);
455}
456
457void diva_os_wakeup_close(void *os_context)
458{
459 diva_um_idi_os_context_t *p_os =
460 (diva_um_idi_os_context_t *) os_context;
461 wake_up_interruptible(&p_os->close_wait);
462}
463
464static
465void diva_um_timer_function(unsigned long data)
466{
467 diva_um_idi_os_context_t *p_os = (diva_um_idi_os_context_t *) data;
468
469 p_os->aborted = 1;
470 wake_up_interruptible(&p_os->read_wait);
471 wake_up_interruptible(&p_os->close_wait);
472 DBG_ERR(("entity removal watchdog"))
473}
474
475/*
476** If application exits without entity removal this function will remove
477** entity and block until removal is complete
478*/
479static int remove_entity(void *entity)
480{
481 struct task_struct *curtask = current;
482 diva_um_idi_os_context_t *p_os;
483
484 diva_um_idi_stop_wdog(entity);
485
486 if (!entity) {
487 DBG_FTL(("Zero entity on remove"))
488 return (0);
489 }
490
491 if (!(p_os =
492 (diva_um_idi_os_context_t *)
493 diva_um_id_get_os_context(entity))) {
494 DBG_FTL(("Zero entity os context on remove"))
495 return (0);
496 }
497
498 if (!divas_um_idi_entity_assigned(entity) || p_os->aborted) {
499 /*
500 Entity is not assigned, also can be removed
501 */
502 return (0);
503 }
504
505 DBG_TRC(("E(%08x) check remove", entity))
506
507 /*
508 If adapter not answers on remove request inside of
509 10 Sec, then adapter is dead
510 */
511 diva_um_idi_start_wdog(entity);
512
513 {
514 DECLARE_WAITQUEUE(wait, curtask);
515
516 add_wait_queue(&p_os->close_wait, &wait);
517 for (;;) {
518 set_current_state(TASK_INTERRUPTIBLE);
519 if (!divas_um_idi_entity_start_remove(entity)
520 || p_os->aborted) {
521 break;
522 }
523 schedule();
524 }
525 set_current_state(TASK_RUNNING);
526 remove_wait_queue(&p_os->close_wait, &wait);
527 }
528
529 DBG_TRC(("E(%08x) start remove", entity))
530 {
531 DECLARE_WAITQUEUE(wait, curtask);
532
533 add_wait_queue(&p_os->close_wait, &wait);
534 for (;;) {
535 set_current_state(TASK_INTERRUPTIBLE);
536 if (!divas_um_idi_entity_assigned(entity)
537 || p_os->aborted) {
538 break;
539 }
540 schedule();
541 }
542 set_current_state(TASK_RUNNING);
543 remove_wait_queue(&p_os->close_wait, &wait);
544 }
545
546 DBG_TRC(("E(%08x) remove complete, aborted:%d", entity,
547 p_os->aborted))
548
549 diva_um_idi_stop_wdog(entity);
550
551 p_os->aborted = 0;
552
553 return (0);
554}
555
556/*
557 * timer watchdog
558 */
559void diva_um_idi_start_wdog(void *entity)
560{
561 diva_um_idi_os_context_t *p_os;
562
563 if (entity &&
564 ((p_os =
565 (diva_um_idi_os_context_t *)
566 diva_um_id_get_os_context(entity)))) {
567 mod_timer(&p_os->diva_timer_id, jiffies + 10 * HZ);
568 }
569}
570
571void diva_um_idi_stop_wdog(void *entity)
572{
573 diva_um_idi_os_context_t *p_os;
574
575 if (entity &&
576 ((p_os =
577 (diva_um_idi_os_context_t *)
578 diva_um_id_get_os_context(entity)))) {
579 del_timer(&p_os->diva_timer_id);
580 }
581}
diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
new file mode 100644
index 000000000000..c9b26e86d183
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/divasmain.c
@@ -0,0 +1,856 @@
1/* $Id: divasmain.c,v 1.55.4.6 2005/02/09 19:28:20 armin Exp $
2 *
3 * Low level driver for Eicon DIVA Server ISDN cards.
4 *
5 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
6 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
7 *
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
10 */
11
12#include <linux/config.h>
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/kernel.h>
16#include <linux/sched.h>
17#include <linux/devfs_fs_kernel.h>
18#include <asm/uaccess.h>
19#include <asm/io.h>
20#include <linux/ioport.h>
21#include <linux/workqueue.h>
22#include <linux/pci.h>
23#include <linux/smp_lock.h>
24#include <linux/interrupt.h>
25#include <linux/list.h>
26#include <linux/poll.h>
27#include <linux/kmod.h>
28
29#include "platform.h"
30#undef ID_MASK
31#undef N_DATA
32#include "pc.h"
33#include "di_defs.h"
34#include "divasync.h"
35#include "diva.h"
36#include "di.h"
37#include "io.h"
38#include "xdi_msg.h"
39#include "xdi_adapter.h"
40#include "xdi_vers.h"
41#include "diva_dma.h"
42#include "diva_pci.h"
43
44static char *main_revision = "$Revision: 1.55.4.6 $";
45
46static int major;
47
48static int dbgmask;
49
50MODULE_DESCRIPTION("Kernel driver for Eicon DIVA Server cards");
51MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
52MODULE_LICENSE("GPL");
53
54module_param(dbgmask, int, 0);
55MODULE_PARM_DESC(dbgmask, "initial debug mask");
56
57static char *DRIVERNAME =
58 "Eicon DIVA Server driver (http://www.melware.net)";
59static char *DRIVERLNAME = "divas";
60static char *DEVNAME = "Divas";
61char *DRIVERRELEASE_DIVAS = "2.0";
62
63extern irqreturn_t diva_os_irq_wrapper(int irq, void *context,
64 struct pt_regs *regs);
65extern int create_divas_proc(void);
66extern void remove_divas_proc(void);
67extern void diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf);
68extern int divasfunc_init(int dbgmask);
69extern void divasfunc_exit(void);
70
71typedef struct _diva_os_thread_dpc {
72 struct tasklet_struct divas_task;
73 diva_os_soft_isr_t *psoft_isr;
74} diva_os_thread_dpc_t;
75
76/* --------------------------------------------------------------------------
77 PCI driver interface section
78 -------------------------------------------------------------------------- */
79/*
80 vendor, device Vendor and device ID to match (or PCI_ANY_ID)
81 subvendor, Subsystem vendor and device ID to match (or PCI_ANY_ID)
82 subdevice
83 class, Device class to match. The class_mask tells which bits
84 class_mask of the class are honored during the comparison.
85 driver_data Data private to the driver.
86 */
87
88#if !defined(PCI_DEVICE_ID_EICON_MAESTRAP_2)
89#define PCI_DEVICE_ID_EICON_MAESTRAP_2 0xE015
90#endif
91
92#if !defined(PCI_DEVICE_ID_EICON_4BRI_VOIP)
93#define PCI_DEVICE_ID_EICON_4BRI_VOIP 0xE016
94#endif
95
96#if !defined(PCI_DEVICE_ID_EICON_4BRI_2_VOIP)
97#define PCI_DEVICE_ID_EICON_4BRI_2_VOIP 0xE017
98#endif
99
100#if !defined(PCI_DEVICE_ID_EICON_BRI2M_2)
101#define PCI_DEVICE_ID_EICON_BRI2M_2 0xE018
102#endif
103
104#if !defined(PCI_DEVICE_ID_EICON_MAESTRAP_2_VOIP)
105#define PCI_DEVICE_ID_EICON_MAESTRAP_2_VOIP 0xE019
106#endif
107
108#if !defined(PCI_DEVICE_ID_EICON_2F)
109#define PCI_DEVICE_ID_EICON_2F 0xE01A
110#endif
111
112#if !defined(PCI_DEVICE_ID_EICON_BRI2M_2_VOIP)
113#define PCI_DEVICE_ID_EICON_BRI2M_2_VOIP 0xE01B
114#endif
115
116/*
117 This table should be sorted by PCI device ID
118 */
119static struct pci_device_id divas_pci_tbl[] = {
120/* Diva Server BRI-2M PCI 0xE010 */
121 {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRA,
122 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_MAESTRA_PCI},
123/* Diva Server 4BRI-8M PCI 0xE012 */
124 {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAQ,
125 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_Q_8M_PCI},
126/* Diva Server 4BRI-8M 2.0 PCI 0xE013 */
127 {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAQ_U,
128 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_Q_8M_V2_PCI},
129/* Diva Server PRI-30M PCI 0xE014 */
130 {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAP,
131 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_P_30M_PCI},
132/* Diva Server PRI 2.0 adapter 0xE015 */
133 {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAP_2,
134 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_P_30M_V2_PCI},
135/* Diva Server Voice 4BRI-8M PCI 0xE016 */
136 {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_4BRI_VOIP,
137 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_VOICE_Q_8M_PCI},
138/* Diva Server Voice 4BRI-8M 2.0 PCI 0xE017 */
139 {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_4BRI_2_VOIP,
140 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI},
141/* Diva Server BRI-2M 2.0 PCI 0xE018 */
142 {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_BRI2M_2,
143 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_B_2M_V2_PCI},
144/* Diva Server Voice PRI 2.0 PCI 0xE019 */
145 {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAP_2_VOIP,
146 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
147 CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI},
148/* Diva Server 2FX 0xE01A */
149 {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_2F,
150 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_B_2F_PCI},
151/* Diva Server Voice BRI-2M 2.0 PCI 0xE01B */
152 {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_BRI2M_2_VOIP,
153 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI},
154 {0,} /* 0 terminated list. */
155};
156MODULE_DEVICE_TABLE(pci, divas_pci_tbl);
157
158static int divas_init_one(struct pci_dev *pdev,
159 const struct pci_device_id *ent);
160static void __devexit divas_remove_one(struct pci_dev *pdev);
161
162static struct pci_driver diva_pci_driver = {
163 .name = "divas",
164 .probe = divas_init_one,
165 .remove = __devexit_p(divas_remove_one),
166 .id_table = divas_pci_tbl,
167};
168
169/*********************************************************
170 ** little helper functions
171 *********************************************************/
172static char *getrev(const char *revision)
173{
174 char *rev;
175 char *p;
176 if ((p = strchr(revision, ':'))) {
177 rev = p + 2;
178 p = strchr(rev, '$');
179 *--p = 0;
180 } else
181 rev = "1.0";
182 return rev;
183}
184
185void diva_log_info(unsigned char *format, ...)
186{
187 va_list args;
188 unsigned char line[160];
189
190 va_start(args, format);
191 vsprintf(line, format, args);
192 va_end(args);
193
194 printk(KERN_INFO "%s: %s\n", DRIVERLNAME, line);
195}
196
197void divas_get_version(char *p)
198{
199 char tmprev[32];
200
201 strcpy(tmprev, main_revision);
202 sprintf(p, "%s: %s(%s) %s(%s) major=%d\n", DRIVERLNAME, DRIVERRELEASE_DIVAS,
203 getrev(tmprev), diva_xdi_common_code_build, DIVA_BUILD, major);
204}
205
206/* --------------------------------------------------------------------------
207 PCI Bus services
208 -------------------------------------------------------------------------- */
209byte diva_os_get_pci_bus(void *pci_dev_handle)
210{
211 struct pci_dev *pdev = (struct pci_dev *) pci_dev_handle;
212 return ((byte) pdev->bus->number);
213}
214
215byte diva_os_get_pci_func(void *pci_dev_handle)
216{
217 struct pci_dev *pdev = (struct pci_dev *) pci_dev_handle;
218 return ((byte) pdev->devfn);
219}
220
221unsigned long divasa_get_pci_irq(unsigned char bus, unsigned char func,
222 void *pci_dev_handle)
223{
224 unsigned char irq = 0;
225 struct pci_dev *dev = (struct pci_dev *) pci_dev_handle;
226
227 irq = dev->irq;
228
229 return ((unsigned long) irq);
230}
231
232unsigned long divasa_get_pci_bar(unsigned char bus, unsigned char func,
233 int bar, void *pci_dev_handle)
234{
235 unsigned long ret = 0;
236 struct pci_dev *dev = (struct pci_dev *) pci_dev_handle;
237
238 if (bar < 6) {
239 ret = dev->resource[bar].start;
240 }
241
242 DBG_TRC(("GOT BAR[%d]=%08x", bar, ret));
243
244 {
245 unsigned long type = (ret & 0x00000001);
246 if (type & PCI_BASE_ADDRESS_SPACE_IO) {
247 DBG_TRC((" I/O"));
248 ret &= PCI_BASE_ADDRESS_IO_MASK;
249 } else {
250 DBG_TRC((" memory"));
251 ret &= PCI_BASE_ADDRESS_MEM_MASK;
252 }
253 DBG_TRC((" final=%08x", ret));
254 }
255
256 return (ret);
257}
258
259void PCIwrite(byte bus, byte func, int offset, void *data, int length,
260 void *pci_dev_handle)
261{
262 struct pci_dev *dev = (struct pci_dev *) pci_dev_handle;
263
264 switch (length) {
265 case 1: /* byte */
266 pci_write_config_byte(dev, offset,
267 *(unsigned char *) data);
268 break;
269 case 2: /* word */
270 pci_write_config_word(dev, offset,
271 *(unsigned short *) data);
272 break;
273 case 4: /* dword */
274 pci_write_config_dword(dev, offset,
275 *(unsigned int *) data);
276 break;
277
278 default: /* buffer */
279 if (!(length % 4) && !(length & 0x03)) { /* Copy as dword */
280 dword *p = (dword *) data;
281 length /= 4;
282
283 while (length--) {
284 pci_write_config_dword(dev, offset,
285 *(unsigned int *)
286 p++);
287 }
288 } else { /* copy as byte stream */
289 byte *p = (byte *) data;
290
291 while (length--) {
292 pci_write_config_byte(dev, offset,
293 *(unsigned char *)
294 p++);
295 }
296 }
297 }
298}
299
300void PCIread(byte bus, byte func, int offset, void *data, int length,
301 void *pci_dev_handle)
302{
303 struct pci_dev *dev = (struct pci_dev *) pci_dev_handle;
304
305 switch (length) {
306 case 1: /* byte */
307 pci_read_config_byte(dev, offset, (unsigned char *) data);
308 break;
309 case 2: /* word */
310 pci_read_config_word(dev, offset, (unsigned short *) data);
311 break;
312 case 4: /* dword */
313 pci_read_config_dword(dev, offset, (unsigned int *) data);
314 break;
315
316 default: /* buffer */
317 if (!(length % 4) && !(length & 0x03)) { /* Copy as dword */
318 dword *p = (dword *) data;
319 length /= 4;
320
321 while (length--) {
322 pci_read_config_dword(dev, offset,
323 (unsigned int *)
324 p++);
325 }
326 } else { /* copy as byte stream */
327 byte *p = (byte *) data;
328
329 while (length--) {
330 pci_read_config_byte(dev, offset,
331 (unsigned char *)
332 p++);
333 }
334 }
335 }
336}
337
338/*
339 Init map with DMA pages. It is not problem if some allocations fail -
340 the channels that will not get one DMA page will use standard PIO
341 interface
342 */
343static void *diva_pci_alloc_consistent(struct pci_dev *hwdev,
344 size_t size,
345 dma_addr_t * dma_handle,
346 void **addr_handle)
347{
348 void *addr = pci_alloc_consistent(hwdev, size, dma_handle);
349
350 *addr_handle = addr;
351
352 return (addr);
353}
354
355void diva_init_dma_map(void *hdev,
356 struct _diva_dma_map_entry **ppmap, int nentries)
357{
358 struct pci_dev *pdev = (struct pci_dev *) hdev;
359 struct _diva_dma_map_entry *pmap =
360 diva_alloc_dma_map(hdev, nentries);
361
362 if (pmap) {
363 int i;
364 dma_addr_t dma_handle;
365 void *cpu_addr;
366 void *addr_handle;
367
368 for (i = 0; i < nentries; i++) {
369 if (!(cpu_addr = diva_pci_alloc_consistent(pdev,
370 PAGE_SIZE,
371 &dma_handle,
372 &addr_handle)))
373 {
374 break;
375 }
376 diva_init_dma_map_entry(pmap, i, cpu_addr,
377 (dword) dma_handle,
378 addr_handle);
379 DBG_TRC(("dma map alloc [%d]=(%08lx:%08x:%08lx)",
380 i, (unsigned long) cpu_addr,
381 (dword) dma_handle,
382 (unsigned long) addr_handle))}
383 }
384
385 *ppmap = pmap;
386}
387
388/*
389 Free all contained in the map entries and memory used by the map
390 Should be always called after adapter removal from DIDD array
391 */
392void diva_free_dma_map(void *hdev, struct _diva_dma_map_entry *pmap)
393{
394 struct pci_dev *pdev = (struct pci_dev *) hdev;
395 int i;
396 dword phys_addr;
397 void *cpu_addr;
398 dma_addr_t dma_handle;
399 void *addr_handle;
400
401 for (i = 0; (pmap != 0); i++) {
402 diva_get_dma_map_entry(pmap, i, &cpu_addr, &phys_addr);
403 if (!cpu_addr) {
404 break;
405 }
406 addr_handle = diva_get_entry_handle(pmap, i);
407 dma_handle = (dma_addr_t) phys_addr;
408 pci_free_consistent(pdev, PAGE_SIZE, addr_handle,
409 dma_handle);
410 DBG_TRC(("dma map free [%d]=(%08lx:%08x:%08lx)", i,
411 (unsigned long) cpu_addr, (dword) dma_handle,
412 (unsigned long) addr_handle))
413 }
414
415 diva_free_dma_mapping(pmap);
416}
417
418
419/*********************************************************
420 ** I/O port utilities
421 *********************************************************/
422
423int
424diva_os_register_io_port(void *adapter, int on, unsigned long port,
425 unsigned long length, const char *name, int id)
426{
427 if (on) {
428 if (!request_region(port, length, name)) {
429 DBG_ERR(("A: I/O: can't register port=%08x", port))
430 return (-1);
431 }
432 } else {
433 release_region(port, length);
434 }
435 return (0);
436}
437
438void __iomem *divasa_remap_pci_bar(diva_os_xdi_adapter_t *a, int id, unsigned long bar, unsigned long area_length)
439{
440 void __iomem *ret = ioremap(bar, area_length);
441 DBG_TRC(("remap(%08x)->%p", bar, ret));
442 return (ret);
443}
444
445void divasa_unmap_pci_bar(void __iomem *bar)
446{
447 if (bar) {
448 iounmap(bar);
449 }
450}
451
452/*********************************************************
453 ** I/O port access
454 *********************************************************/
455byte __inline__ inpp(void __iomem *addr)
456{
457 return (inb((unsigned long) addr));
458}
459
460word __inline__ inppw(void __iomem *addr)
461{
462 return (inw((unsigned long) addr));
463}
464
465void __inline__ inppw_buffer(void __iomem *addr, void *P, int length)
466{
467 insw((unsigned long) addr, (word *) P, length >> 1);
468}
469
470void __inline__ outppw_buffer(void __iomem *addr, void *P, int length)
471{
472 outsw((unsigned long) addr, (word *) P, length >> 1);
473}
474
475void __inline__ outppw(void __iomem *addr, word w)
476{
477 outw(w, (unsigned long) addr);
478}
479
480void __inline__ outpp(void __iomem *addr, word p)
481{
482 outb(p, (unsigned long) addr);
483}
484
485/* --------------------------------------------------------------------------
486 IRQ request / remove
487 -------------------------------------------------------------------------- */
488int diva_os_register_irq(void *context, byte irq, const char *name)
489{
490 int result = request_irq(irq, diva_os_irq_wrapper,
491 SA_INTERRUPT | SA_SHIRQ, name, context);
492 return (result);
493}
494
495void diva_os_remove_irq(void *context, byte irq)
496{
497 free_irq(irq, context);
498}
499
500/* --------------------------------------------------------------------------
501 DPC framework implementation
502 -------------------------------------------------------------------------- */
503static void diva_os_dpc_proc(unsigned long context)
504{
505 diva_os_thread_dpc_t *psoft_isr = (diva_os_thread_dpc_t *) context;
506 diva_os_soft_isr_t *pisr = psoft_isr->psoft_isr;
507
508 (*(pisr->callback)) (pisr, pisr->callback_context);
509}
510
511int diva_os_initialize_soft_isr(diva_os_soft_isr_t * psoft_isr,
512 diva_os_soft_isr_callback_t callback,
513 void *callback_context)
514{
515 diva_os_thread_dpc_t *pdpc;
516
517 pdpc = (diva_os_thread_dpc_t *) diva_os_malloc(0, sizeof(*pdpc));
518 if (!(psoft_isr->object = pdpc)) {
519 return (-1);
520 }
521 memset(pdpc, 0x00, sizeof(*pdpc));
522 psoft_isr->callback = callback;
523 psoft_isr->callback_context = callback_context;
524 pdpc->psoft_isr = psoft_isr;
525 tasklet_init(&pdpc->divas_task, diva_os_dpc_proc, (unsigned long)pdpc);
526
527 return (0);
528}
529
530int diva_os_schedule_soft_isr(diva_os_soft_isr_t * psoft_isr)
531{
532 if (psoft_isr && psoft_isr->object) {
533 diva_os_thread_dpc_t *pdpc =
534 (diva_os_thread_dpc_t *) psoft_isr->object;
535
536 tasklet_schedule(&pdpc->divas_task);
537 }
538
539 return (1);
540}
541
542int diva_os_cancel_soft_isr(diva_os_soft_isr_t * psoft_isr)
543{
544 return (0);
545}
546
547void diva_os_remove_soft_isr(diva_os_soft_isr_t * psoft_isr)
548{
549 if (psoft_isr && psoft_isr->object) {
550 diva_os_thread_dpc_t *pdpc =
551 (diva_os_thread_dpc_t *) psoft_isr->object;
552 void *mem;
553
554 tasklet_kill(&pdpc->divas_task);
555 flush_scheduled_work();
556 mem = psoft_isr->object;
557 psoft_isr->object = NULL;
558 diva_os_free(0, mem);
559 }
560}
561
562/*
563 * kernel/user space copy functions
564 */
565static int
566xdi_copy_to_user(void *os_handle, void __user *dst, const void *src, int length)
567{
568 if (copy_to_user(dst, src, length)) {
569 return (-EFAULT);
570 }
571 return (length);
572}
573
574static int
575xdi_copy_from_user(void *os_handle, void *dst, const void __user *src, int length)
576{
577 if (copy_from_user(dst, src, length)) {
578 return (-EFAULT);
579 }
580 return (length);
581}
582
583/*
584 * device node operations
585 */
586static int divas_open(struct inode *inode, struct file *file)
587{
588 return (0);
589}
590
591static int divas_release(struct inode *inode, struct file *file)
592{
593 if (file->private_data) {
594 diva_xdi_close_adapter(file->private_data, file);
595 }
596 return (0);
597}
598
599static ssize_t divas_write(struct file *file, const char __user *buf,
600 size_t count, loff_t * ppos)
601{
602 int ret = -EINVAL;
603
604 if (!file->private_data) {
605 file->private_data = diva_xdi_open_adapter(file, buf,
606 count,
607 xdi_copy_from_user);
608 }
609 if (!file->private_data) {
610 return (-ENODEV);
611 }
612
613 ret = diva_xdi_write(file->private_data, file,
614 buf, count, xdi_copy_from_user);
615 switch (ret) {
616 case -1: /* Message should be removed from rx mailbox first */
617 ret = -EBUSY;
618 break;
619 case -2: /* invalid adapter was specified in this call */
620 ret = -ENOMEM;
621 break;
622 case -3:
623 ret = -ENXIO;
624 break;
625 }
626 DBG_TRC(("write: ret %d", ret));
627 return (ret);
628}
629
630static ssize_t divas_read(struct file *file, char __user *buf,
631 size_t count, loff_t * ppos)
632{
633 int ret = -EINVAL;
634
635 if (!file->private_data) {
636 file->private_data = diva_xdi_open_adapter(file, buf,
637 count,
638 xdi_copy_from_user);
639 }
640 if (!file->private_data) {
641 return (-ENODEV);
642 }
643
644 ret = diva_xdi_read(file->private_data, file,
645 buf, count, xdi_copy_to_user);
646 switch (ret) {
647 case -1: /* RX mailbox is empty */
648 ret = -EAGAIN;
649 break;
650 case -2: /* no memory, mailbox was cleared, last command is failed */
651 ret = -ENOMEM;
652 break;
653 case -3: /* can't copy to user, retry */
654 ret = -EFAULT;
655 break;
656 }
657 DBG_TRC(("read: ret %d", ret));
658 return (ret);
659}
660
661static unsigned int divas_poll(struct file *file, poll_table * wait)
662{
663 if (!file->private_data) {
664 return (POLLERR);
665 }
666 return (POLLIN | POLLRDNORM);
667}
668
669static struct file_operations divas_fops = {
670 .owner = THIS_MODULE,
671 .llseek = no_llseek,
672 .read = divas_read,
673 .write = divas_write,
674 .poll = divas_poll,
675 .open = divas_open,
676 .release = divas_release
677};
678
679static void divas_unregister_chrdev(void)
680{
681 devfs_remove(DEVNAME);
682 unregister_chrdev(major, DEVNAME);
683}
684
685static int DIVA_INIT_FUNCTION divas_register_chrdev(void)
686{
687 if ((major = register_chrdev(0, DEVNAME, &divas_fops)) < 0)
688 {
689 printk(KERN_ERR "%s: failed to create /dev entry.\n",
690 DRIVERLNAME);
691 return (0);
692 }
693 devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, DEVNAME);
694
695 return (1);
696}
697
698/* --------------------------------------------------------------------------
699 PCI driver section
700 -------------------------------------------------------------------------- */
701static int __devinit divas_init_one(struct pci_dev *pdev,
702 const struct pci_device_id *ent)
703{
704 void *pdiva = NULL;
705 u8 pci_latency;
706 u8 new_latency = 32;
707
708 DBG_TRC(("%s bus: %08x fn: %08x insertion.\n",
709 CardProperties[ent->driver_data].Name,
710 pdev->bus->number, pdev->devfn))
711 printk(KERN_INFO "%s: %s bus: %08x fn: %08x insertion.\n",
712 DRIVERLNAME, CardProperties[ent->driver_data].Name,
713 pdev->bus->number, pdev->devfn);
714
715 if (pci_enable_device(pdev)) {
716 DBG_TRC(("%s: %s bus: %08x fn: %08x device init failed.\n",
717 DRIVERLNAME,
718 CardProperties[ent->driver_data].Name,
719 pdev->bus->number,
720 pdev->devfn))
721 printk(KERN_ERR
722 "%s: %s bus: %08x fn: %08x device init failed.\n",
723 DRIVERLNAME,
724 CardProperties[ent->driver_data].
725 Name, pdev->bus->number,
726 pdev->devfn);
727 return (-EIO);
728 }
729
730 pci_set_master(pdev);
731
732 pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
733 if (!pci_latency) {
734 DBG_TRC(("%s: bus: %08x fn: %08x fix latency.\n",
735 DRIVERLNAME, pdev->bus->number, pdev->devfn))
736 printk(KERN_INFO
737 "%s: bus: %08x fn: %08x fix latency.\n",
738 DRIVERLNAME, pdev->bus->number, pdev->devfn);
739 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency);
740 }
741
742 if (!(pdiva = diva_driver_add_card(pdev, ent->driver_data))) {
743 DBG_TRC(("%s: %s bus: %08x fn: %08x card init failed.\n",
744 DRIVERLNAME,
745 CardProperties[ent->driver_data].Name,
746 pdev->bus->number,
747 pdev->devfn))
748 printk(KERN_ERR
749 "%s: %s bus: %08x fn: %08x card init failed.\n",
750 DRIVERLNAME,
751 CardProperties[ent->driver_data].
752 Name, pdev->bus->number,
753 pdev->devfn);
754 return (-EIO);
755 }
756
757 pci_set_drvdata(pdev, pdiva);
758
759 return (0);
760}
761
762static void __devexit divas_remove_one(struct pci_dev *pdev)
763{
764 void *pdiva = pci_get_drvdata(pdev);
765
766 DBG_TRC(("bus: %08x fn: %08x removal.\n",
767 pdev->bus->number, pdev->devfn))
768 printk(KERN_INFO "%s: bus: %08x fn: %08x removal.\n",
769 DRIVERLNAME, pdev->bus->number, pdev->devfn);
770
771 if (pdiva) {
772 diva_driver_remove_card(pdiva);
773 }
774
775}
776
777/* --------------------------------------------------------------------------
778 Driver Load / Startup
779 -------------------------------------------------------------------------- */
780static int DIVA_INIT_FUNCTION divas_init(void)
781{
782 char tmprev[50];
783 int ret = 0;
784
785 printk(KERN_INFO "%s\n", DRIVERNAME);
786 printk(KERN_INFO "%s: Rel:%s Rev:", DRIVERLNAME, DRIVERRELEASE_DIVAS);
787 strcpy(tmprev, main_revision);
788 printk("%s Build: %s(%s)\n", getrev(tmprev),
789 diva_xdi_common_code_build, DIVA_BUILD);
790 printk(KERN_INFO "%s: support for: ", DRIVERLNAME);
791#ifdef CONFIG_ISDN_DIVAS_BRIPCI
792 printk("BRI/PCI ");
793#endif
794#ifdef CONFIG_ISDN_DIVAS_PRIPCI
795 printk("PRI/PCI ");
796#endif
797 printk("adapters\n");
798
799 if (!divasfunc_init(dbgmask)) {
800 printk(KERN_ERR "%s: failed to connect to DIDD.\n",
801 DRIVERLNAME);
802 ret = -EIO;
803 goto out;
804 }
805
806 if (!divas_register_chrdev()) {
807#ifdef MODULE
808 divasfunc_exit();
809#endif
810 ret = -EIO;
811 goto out;
812 }
813
814 if (!create_divas_proc()) {
815#ifdef MODULE
816 remove_divas_proc();
817 divas_unregister_chrdev();
818 divasfunc_exit();
819#endif
820 printk(KERN_ERR "%s: failed to create proc entry.\n",
821 DRIVERLNAME);
822 ret = -EIO;
823 goto out;
824 }
825
826 if ((ret = pci_register_driver(&diva_pci_driver))) {
827#ifdef MODULE
828 remove_divas_proc();
829 divas_unregister_chrdev();
830 divasfunc_exit();
831#endif
832 printk(KERN_ERR "%s: failed to init pci driver.\n",
833 DRIVERLNAME);
834 goto out;
835 }
836 printk(KERN_INFO "%s: started with major %d\n", DRIVERLNAME, major);
837
838 out:
839 return (ret);
840}
841
842/* --------------------------------------------------------------------------
843 Driver Unload
844 -------------------------------------------------------------------------- */
845static void DIVA_EXIT_FUNCTION divas_exit(void)
846{
847 pci_unregister_driver(&diva_pci_driver);
848 remove_divas_proc();
849 divas_unregister_chrdev();
850 divasfunc_exit();
851
852 printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
853}
854
855module_init(divas_init);
856module_exit(divas_exit);
diff --git a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c
new file mode 100644
index 000000000000..b6435589d459
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/divasproc.c
@@ -0,0 +1,441 @@
1/* $Id: divasproc.c,v 1.19.4.3 2005/01/31 12:22:20 armin Exp $
2 *
3 * Low level driver for Eicon DIVA Server ISDN cards.
4 * /proc functions
5 *
6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 */
12
13#include <linux/config.h>
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/poll.h>
17#include <linux/proc_fs.h>
18#include <linux/list.h>
19#include <asm/uaccess.h>
20
21#include "platform.h"
22#include "debuglib.h"
23#undef ID_MASK
24#undef N_DATA
25#include "pc.h"
26#include "di_defs.h"
27#include "divasync.h"
28#include "di.h"
29#include "io.h"
30#include "xdi_msg.h"
31#include "xdi_adapter.h"
32#include "diva.h"
33#include "diva_pci.h"
34
35
36extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER];
37extern void divas_get_version(char *);
38extern void diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf);
39
40/*********************************************************
41 ** Functions for /proc interface / File operations
42 *********************************************************/
43
44static char *divas_proc_name = "divas";
45static char *adapter_dir_name = "adapter";
46static char *info_proc_name = "info";
47static char *grp_opt_proc_name = "group_optimization";
48static char *d_l1_down_proc_name = "dynamic_l1_down";
49
50/*
51** "divas" entry
52*/
53
54extern struct proc_dir_entry *proc_net_eicon;
55static struct proc_dir_entry *divas_proc_entry = NULL;
56
57static ssize_t
58divas_read(struct file *file, char __user *buf, size_t count, loff_t * off)
59{
60 int len = 0;
61 int cadapter;
62 char tmpbuf[80];
63 char tmpser[16];
64
65 if (*off)
66 return 0;
67
68 divas_get_version(tmpbuf);
69 if (copy_to_user(buf + len, &tmpbuf, strlen(tmpbuf)))
70 return -EFAULT;
71 len += strlen(tmpbuf);
72
73 for (cadapter = 0; cadapter < MAX_ADAPTER; cadapter++) {
74 if (IoAdapters[cadapter]) {
75 diva_get_vserial_number(IoAdapters[cadapter],
76 tmpser);
77 sprintf(tmpbuf,
78 "%2d: %-30s Serial:%-10s IRQ:%2d\n",
79 cadapter + 1,
80 IoAdapters[cadapter]->Properties.Name,
81 tmpser,
82 IoAdapters[cadapter]->irq_info.irq_nr);
83 if ((strlen(tmpbuf) + len) > count)
84 break;
85 if (copy_to_user
86 (buf + len, &tmpbuf,
87 strlen(tmpbuf))) return -EFAULT;
88 len += strlen(tmpbuf);
89 }
90 }
91
92 *off += len;
93 return (len);
94}
95
96static ssize_t
97divas_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
98{
99 return (-ENODEV);
100}
101
102static unsigned int divas_poll(struct file *file, poll_table * wait)
103{
104 return (POLLERR);
105}
106
107static int divas_open(struct inode *inode, struct file *file)
108{
109 return nonseekable_open(inode, file);
110}
111
112static int divas_close(struct inode *inode, struct file *file)
113{
114 return (0);
115}
116
117static struct file_operations divas_fops = {
118 .owner = THIS_MODULE,
119 .llseek = no_llseek,
120 .read = divas_read,
121 .write = divas_write,
122 .poll = divas_poll,
123 .open = divas_open,
124 .release = divas_close
125};
126
127int create_divas_proc(void)
128{
129 divas_proc_entry = create_proc_entry(divas_proc_name,
130 S_IFREG | S_IRUGO,
131 proc_net_eicon);
132 if (!divas_proc_entry)
133 return (0);
134
135 divas_proc_entry->proc_fops = &divas_fops;
136 divas_proc_entry->owner = THIS_MODULE;
137
138 return (1);
139}
140
141void remove_divas_proc(void)
142{
143 if (divas_proc_entry) {
144 remove_proc_entry(divas_proc_name, proc_net_eicon);
145 divas_proc_entry = NULL;
146 }
147}
148
149/*
150** write group_optimization
151*/
152static int
153write_grp_opt(struct file *file, const char __user *buffer, unsigned long count,
154 void *data)
155{
156 diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
157 PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
158
159 if ((count == 1) || (count == 2)) {
160 char c;
161 if (get_user(c, buffer))
162 return -EFAULT;
163 switch (c) {
164 case '0':
165 IoAdapter->capi_cfg.cfg_1 &=
166 ~DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON;
167 break;
168 case '1':
169 IoAdapter->capi_cfg.cfg_1 |=
170 DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON;
171 break;
172 default:
173 return (-EINVAL);
174 }
175 return (count);
176 }
177 return (-EINVAL);
178}
179
180/*
181** write dynamic_l1_down
182*/
183static int
184write_d_l1_down(struct file *file, const char __user *buffer, unsigned long count,
185 void *data)
186{
187 diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
188 PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
189
190 if ((count == 1) || (count == 2)) {
191 char c;
192 if (get_user(c, buffer))
193 return -EFAULT;
194 switch (c) {
195 case '0':
196 IoAdapter->capi_cfg.cfg_1 &=
197 ~DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON;
198 break;
199 case '1':
200 IoAdapter->capi_cfg.cfg_1 |=
201 DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON;
202 break;
203 default:
204 return (-EINVAL);
205 }
206 return (count);
207 }
208 return (-EINVAL);
209}
210
211
212/*
213** read dynamic_l1_down
214*/
215static int
216read_d_l1_down(char *page, char **start, off_t off, int count, int *eof,
217 void *data)
218{
219 int len = 0;
220 diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
221 PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
222
223 len += sprintf(page + len, "%s\n",
224 (IoAdapter->capi_cfg.
225 cfg_1 & DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ? "1" :
226 "0");
227
228 if (off + count >= len)
229 *eof = 1;
230 if (len < off)
231 return 0;
232 *start = page + off;
233 return ((count < len - off) ? count : len - off);
234}
235
236/*
237** read group_optimization
238*/
239static int
240read_grp_opt(char *page, char **start, off_t off, int count, int *eof,
241 void *data)
242{
243 int len = 0;
244 diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
245 PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
246
247 len += sprintf(page + len, "%s\n",
248 (IoAdapter->capi_cfg.
249 cfg_1 & DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON)
250 ? "1" : "0");
251
252 if (off + count >= len)
253 *eof = 1;
254 if (len < off)
255 return 0;
256 *start = page + off;
257 return ((count < len - off) ? count : len - off);
258}
259
260/*
261** info write
262*/
263static int
264info_write(struct file *file, const char __user *buffer, unsigned long count,
265 void *data)
266{
267 diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
268 PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
269 char c[4];
270
271 if (count <= 4)
272 return -EINVAL;
273
274 if (copy_from_user(c, buffer, 4))
275 return -EFAULT;
276
277 /* this is for test purposes only */
278 if (!memcmp(c, "trap", 4)) {
279 (*(IoAdapter->os_trap_nfy_Fnc)) (IoAdapter, IoAdapter->ANum);
280 return (count);
281 }
282 return (-EINVAL);
283}
284
285/*
286** info read
287*/
288static int
289info_read(char *page, char **start, off_t off, int count, int *eof,
290 void *data)
291{
292 int i = 0;
293 int len = 0;
294 char *p;
295 char tmpser[16];
296 diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
297 PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
298
299 len +=
300 sprintf(page + len, "Name : %s\n",
301 IoAdapter->Properties.Name);
302 len += sprintf(page + len, "DSP state : %08x\n", a->dsp_mask);
303 len += sprintf(page + len, "Channels : %02d\n",
304 IoAdapter->Properties.Channels);
305 len += sprintf(page + len, "E. max/used : %03d/%03d\n",
306 IoAdapter->e_max, IoAdapter->e_count);
307 diva_get_vserial_number(IoAdapter, tmpser);
308 len += sprintf(page + len, "Serial : %s\n", tmpser);
309 len +=
310 sprintf(page + len, "IRQ : %d\n",
311 IoAdapter->irq_info.irq_nr);
312 len += sprintf(page + len, "CardIndex : %d\n", a->CardIndex);
313 len += sprintf(page + len, "CardOrdinal : %d\n", a->CardOrdinal);
314 len += sprintf(page + len, "Controller : %d\n", a->controller);
315 len += sprintf(page + len, "Bus-Type : %s\n",
316 (a->Bus ==
317 DIVAS_XDI_ADAPTER_BUS_ISA) ? "ISA" : "PCI");
318 len += sprintf(page + len, "Port-Name : %s\n", a->port_name);
319 if (a->Bus == DIVAS_XDI_ADAPTER_BUS_PCI) {
320 len +=
321 sprintf(page + len, "PCI-bus : %d\n",
322 a->resources.pci.bus);
323 len +=
324 sprintf(page + len, "PCI-func : %d\n",
325 a->resources.pci.func);
326 for (i = 0; i < 8; i++) {
327 if (a->resources.pci.bar[i]) {
328 len +=
329 sprintf(page + len,
330 "Mem / I/O %d : 0x%x / mapped : 0x%lx",
331 i, a->resources.pci.bar[i],
332 (unsigned long) a->resources.
333 pci.addr[i]);
334 if (a->resources.pci.length[i]) {
335 len +=
336 sprintf(page + len,
337 " / length : %d",
338 a->resources.pci.
339 length[i]);
340 }
341 len += sprintf(page + len, "\n");
342 }
343 }
344 }
345 if ((!a->xdi_adapter.port) &&
346 ((!a->xdi_adapter.ram) ||
347 (!a->xdi_adapter.reset)
348 || (!a->xdi_adapter.cfg))) {
349 if (!IoAdapter->irq_info.irq_nr) {
350 p = "slave";
351 } else {
352 p = "out of service";
353 }
354 } else if (a->xdi_adapter.trapped) {
355 p = "trapped";
356 } else if (a->xdi_adapter.Initialized) {
357 p = "active";
358 } else {
359 p = "ready";
360 }
361 len += sprintf(page + len, "State : %s\n", p);
362
363 if (off + count >= len)
364 *eof = 1;
365 if (len < off)
366 return 0;
367 *start = page + off;
368 return ((count < len - off) ? count : len - off);
369}
370
371/*
372** adapter proc init/de-init
373*/
374
375/* --------------------------------------------------------------------------
376 Create adapter directory and files in proc file system
377 -------------------------------------------------------------------------- */
378int create_adapter_proc(diva_os_xdi_adapter_t * a)
379{
380 struct proc_dir_entry *de, *pe;
381 char tmp[16];
382
383 sprintf(tmp, "%s%d", adapter_dir_name, a->controller);
384 if (!(de = create_proc_entry(tmp, S_IFDIR, proc_net_eicon)))
385 return (0);
386 a->proc_adapter_dir = (void *) de;
387
388 if (!(pe =
389 create_proc_entry(info_proc_name, S_IFREG | S_IRUGO | S_IWUSR, de)))
390 return (0);
391 a->proc_info = (void *) pe;
392 pe->write_proc = info_write;
393 pe->read_proc = info_read;
394 pe->data = a;
395
396 if ((pe = create_proc_entry(grp_opt_proc_name,
397 S_IFREG | S_IRUGO | S_IWUSR, de))) {
398 a->proc_grp_opt = (void *) pe;
399 pe->write_proc = write_grp_opt;
400 pe->read_proc = read_grp_opt;
401 pe->data = a;
402 }
403 if ((pe = create_proc_entry(d_l1_down_proc_name,
404 S_IFREG | S_IRUGO | S_IWUSR, de))) {
405 a->proc_d_l1_down = (void *) pe;
406 pe->write_proc = write_d_l1_down;
407 pe->read_proc = read_d_l1_down;
408 pe->data = a;
409 }
410
411 DBG_TRC(("proc entry %s created", tmp));
412
413 return (1);
414}
415
416/* --------------------------------------------------------------------------
417 Remove adapter directory and files in proc file system
418 -------------------------------------------------------------------------- */
419void remove_adapter_proc(diva_os_xdi_adapter_t * a)
420{
421 char tmp[16];
422
423 if (a->proc_adapter_dir) {
424 if (a->proc_d_l1_down) {
425 remove_proc_entry(d_l1_down_proc_name,
426 (struct proc_dir_entry *) a->proc_adapter_dir);
427 }
428 if (a->proc_grp_opt) {
429 remove_proc_entry(grp_opt_proc_name,
430 (struct proc_dir_entry *) a->proc_adapter_dir);
431 }
432 if (a->proc_info) {
433 remove_proc_entry(info_proc_name,
434 (struct proc_dir_entry *) a->proc_adapter_dir);
435 }
436 sprintf(tmp, "%s%d", adapter_dir_name, a->controller);
437 remove_proc_entry(tmp, proc_net_eicon);
438 DBG_TRC(("proc entry %s%d removed", adapter_dir_name,
439 a->controller));
440 }
441}
diff --git a/drivers/isdn/hardware/eicon/divasync.h b/drivers/isdn/hardware/eicon/divasync.h
new file mode 100644
index 000000000000..0a5be7f969f2
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/divasync.h
@@ -0,0 +1,490 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef __DIVA_SYNC__H
27#define __DIVA_SYNC__H
28#define IDI_SYNC_REQ_REMOVE 0x00
29#define IDI_SYNC_REQ_GET_NAME 0x01
30#define IDI_SYNC_REQ_GET_SERIAL 0x02
31#define IDI_SYNC_REQ_SET_POSTCALL 0x03
32#define IDI_SYNC_REQ_GET_XLOG 0x04
33#define IDI_SYNC_REQ_GET_FEATURES 0x05
34#define IDI_SYNC_REQ_USB_REGISTER 0x06
35#define IDI_SYNC_REQ_USB_RELEASE 0x07
36#define IDI_SYNC_REQ_USB_ADD_DEVICE 0x08
37#define IDI_SYNC_REQ_USB_START_DEVICE 0x09
38#define IDI_SYNC_REQ_USB_STOP_DEVICE 0x0A
39#define IDI_SYNC_REQ_USB_REMOVE_DEVICE 0x0B
40#define IDI_SYNC_REQ_GET_CARDTYPE 0x0C
41#define IDI_SYNC_REQ_GET_DBG_XLOG 0x0D
42#define DIVA_USB
43#define DIVA_USB_REQ 0xAC
44#define DIVA_USB_TEST 0xAB
45#define DIVA_USB_ADD_ADAPTER 0xAC
46#define DIVA_USB_REMOVE_ADAPTER 0xAD
47#define IDI_SYNC_REQ_SERIAL_HOOK 0x80
48#define IDI_SYNC_REQ_XCHANGE_STATUS 0x81
49#define IDI_SYNC_REQ_USB_HOOK 0x82
50#define IDI_SYNC_REQ_PORTDRV_HOOK 0x83
51#define IDI_SYNC_REQ_SLI 0x84 /* SLI request from 3signal modem drivers */
52#define IDI_SYNC_REQ_RECONFIGURE 0x85
53#define IDI_SYNC_REQ_RESET 0x86
54#define IDI_SYNC_REQ_GET_85X_DEVICE_DATA 0x87
55#define IDI_SYNC_REQ_LOCK_85X 0x88
56#define IDI_SYNC_REQ_DIVA_85X_USB_DATA_EXCHANGE 0x99
57#define IDI_SYNC_REQ_DIPORT_EXCHANGE_REQ 0x98
58#define IDI_SYNC_REQ_GET_85X_EXT_PORT_TYPE 0xA0
59/******************************************************************************/
60#define IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES 0x92
61/*
62 To receive XDI features:
63 1. set 'buffer_length_in_bytes' to length of you buffer
64 2. set 'features' to pointer to your buffer
65 3. issue synchronous request to XDI
66 4. Check that feature 'DIVA_XDI_EXTENDED_FEATURES_VALID' is present
67 after call. This feature does indicate that your request
68 was processed and XDI does support this synchronous request
69 5. if on return bit 31 (0x80000000) in 'buffer_length_in_bytes' is
70 set then provided buffer was too small, and bits 30-0 does
71 contain necessary length of buffer.
72 in this case only features that do find place in the buffer
73 are indicated to caller
74*/
75typedef struct _diva_xdi_get_extended_xdi_features {
76 dword buffer_length_in_bytes;
77 byte *features;
78} diva_xdi_get_extended_xdi_features_t;
79/*
80 features[0]
81 */
82#define DIVA_XDI_EXTENDED_FEATURES_VALID 0x01
83#define DIVA_XDI_EXTENDED_FEATURE_CMA 0x02
84#define DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR 0x04
85#define DIVA_XDI_EXTENDED_FEATURE_CAPI_PRMS 0x08
86#define DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC 0x10
87#define DIVA_XDI_EXTENDED_FEATURE_RX_DMA 0x20
88#define DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA 0x40
89#define DIVA_XDI_EXTENDED_FEATURE_WIDE_ID 0x80
90#define DIVA_XDI_EXTENDED_FEATURES_MAX_SZ 1
91/******************************************************************************/
92#define IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR 0x93
93typedef struct _diva_xdi_get_adapter_sdram_bar {
94 dword bar;
95} diva_xdi_get_adapter_sdram_bar_t;
96/******************************************************************************/
97#define IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS 0x94
98/*
99 CAPI Parameters will be written in the caller's buffer
100 */
101typedef struct _diva_xdi_get_capi_parameters {
102 dword structure_length;
103 byte flag_dynamic_l1_down;
104 byte group_optimization_enabled;
105} diva_xdi_get_capi_parameters_t;
106/******************************************************************************/
107#define IDI_SYNC_REQ_XDI_GET_LOGICAL_ADAPTER_NUMBER 0x95
108/*
109 Get logical adapter number, as assigned by XDI
110 'controller' is starting with zero 'sub' controller number
111 in case of one adapter that supports multiple interfaces
112 'controller' is zero for Master adapter (and adapter that supports
113 only one interface)
114 */
115typedef struct _diva_xdi_get_logical_adapter_number {
116 dword logical_adapter_number;
117 dword controller;
118 dword total_controllers;
119} diva_xdi_get_logical_adapter_number_s_t;
120/******************************************************************************/
121#define IDI_SYNC_REQ_UP1DM_OPERATION 0x96
122/******************************************************************************/
123#define IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION 0x97
124#define IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC 0x01
125#define IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE 0x02
126typedef struct _diva_xdi_dma_descriptor_operation {
127 int operation;
128 int descriptor_number;
129 void* descriptor_address;
130 dword descriptor_magic;
131} diva_xdi_dma_descriptor_operation_t;
132/******************************************************************************/
133#define IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY 0x01
134#define IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY 0x02
135#define IDI_SYNC_REQ_DIDD_ADD_ADAPTER 0x03
136#define IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER 0x04
137#define IDI_SYNC_REQ_DIDD_READ_ADAPTER_ARRAY 0x05
138#define IDI_SYNC_REQ_DIDD_GET_CFG_LIB_IFC 0x10
139typedef struct _diva_didd_adapter_notify {
140 dword handle; /* Notification handle */
141 void * callback;
142 void * context;
143} diva_didd_adapter_notify_t;
144typedef struct _diva_didd_add_adapter {
145 void * descriptor;
146} diva_didd_add_adapter_t;
147typedef struct _diva_didd_remove_adapter {
148 IDI_CALL p_request;
149} diva_didd_remove_adapter_t;
150typedef struct _diva_didd_read_adapter_array {
151 void * buffer;
152 dword length;
153} diva_didd_read_adapter_array_t;
154typedef struct _diva_didd_get_cfg_lib_ifc {
155 void* ifc;
156} diva_didd_get_cfg_lib_ifc_t;
157/******************************************************************************/
158#define IDI_SYNC_REQ_XDI_GET_STREAM 0x91
159#define DIVA_XDI_SYNCHRONOUS_SERVICE 0x01
160#define DIVA_XDI_DMA_SERVICE 0x02
161#define DIVA_XDI_AUTO_SERVICE 0x03
162#define DIVA_ISTREAM_COMPLETE_NOTIFY 0
163#define DIVA_ISTREAM_COMPLETE_READ 1
164#define DIVA_ISTREAM_COMPLETE_WRITE 2
165typedef struct _diva_xdi_stream_interface {
166 unsigned char Id; /* filled by XDI client */
167 unsigned char provided_service; /* filled by XDI */
168 unsigned char requested_service; /* filled by XDI Client */
169 void* xdi_context; /* filled by XDI */
170 void* client_context; /* filled by XDI client */
171 int (*write)(void* context,
172 int Id,
173 void* data,
174 int length,
175 int final,
176 byte usr1,
177 byte usr2);
178 int (*read)(void* context,
179 int Id,
180 void* data,
181 int max_length,
182 int* final,
183 byte* usr1,
184 byte* usr2);
185 int (*complete)(void* client_context,
186 int Id,
187 int what,
188 void* data,
189 int length,
190 int* final);
191} diva_xdi_stream_interface_t;
192/******************************************************************************/
193/*
194 * IDI_SYNC_REQ_SERIAL_HOOK - special interface for the DIVA Mobile card
195 */
196typedef struct
197{ unsigned char LineState; /* Modem line state (STATUS_R) */
198#define SERIAL_GSM_CELL 0x01 /* GSM or CELL cable attached */
199 unsigned char CardState; /* PCMCIA card state (0 = down) */
200 unsigned char IsdnState; /* ISDN layer 1 state (0 = down)*/
201 unsigned char HookState; /* current logical hook state */
202#define SERIAL_ON_HOOK 0x02 /* set in DIVA CTRL_R register */
203} SERIAL_STATE;
204typedef int ( * SERIAL_INT_CB) (void *Context) ;
205typedef int ( * SERIAL_DPC_CB) (void *Context) ;
206typedef unsigned char ( * SERIAL_I_SYNC) (void *Context) ;
207typedef struct
208{ /* 'Req' and 'Rc' must be at the same place as in the ENTITY struct */
209 unsigned char Req; /* request (must be always 0) */
210 unsigned char Rc; /* return code (is the request) */
211 unsigned char Function; /* private function code */
212#define SERIAL_HOOK_ATTACH 0x81
213#define SERIAL_HOOK_STATUS 0x82
214#define SERIAL_HOOK_I_SYNC 0x83
215#define SERIAL_HOOK_NOECHO 0x84
216#define SERIAL_HOOK_RING 0x85
217#define SERIAL_HOOK_DETACH 0x8f
218 unsigned char Flags; /* function refinements */
219 /* parameters passed by the the ATTACH request */
220 SERIAL_INT_CB InterruptHandler; /* called on each interrupt */
221 SERIAL_DPC_CB DeferredHandler; /* called on hook state changes */
222 void *HandlerContext; /* context for both handlers */
223 /* return values for both the ATTACH and the STATUS request */
224 unsigned long IoBase; /* IO port assigned to UART */
225 SERIAL_STATE State;
226 /* parameters and return values for the I_SYNC function */
227 SERIAL_I_SYNC SyncFunction; /* to be called synchronized */
228 void *SyncContext; /* context for this function */
229 unsigned char SyncResult; /* return value of function */
230} SERIAL_HOOK;
231/*
232 * IDI_SYNC_REQ_XCHANGE_STATUS - exchange the status between IDI and WMP
233 * IDI_SYNC_REQ_RECONFIGURE - reconfiguration of IDI from WMP
234 */
235typedef struct
236{ /* 'Req' and 'Rc' must be at the same place as in the ENTITY struct */
237 unsigned char Req; /* request (must be always 0) */
238 unsigned char Rc; /* return code (is the request) */
239#define DRIVER_STATUS_BOOT 0xA1
240#define DRIVER_STATUS_INIT_DEV 0xA2
241#define DRIVER_STATUS_RUNNING 0xA3
242#define DRIVER_STATUS_SHUTDOWN 0xAF
243#define DRIVER_STATUS_TRAPPED 0xAE
244 unsigned char wmpStatus; /* exported by WMP */
245 unsigned char idiStatus; /* exported by IDI */
246 unsigned long wizProto ; /* from WMP registry to IDI */
247 /* the cardtype value is defined by cardtype.h */
248 unsigned long cardType ; /* from IDI registry to WMP */
249 unsigned long nt2 ; /* from IDI registry to WMP */
250 unsigned long permanent ; /* from IDI registry to WMP */
251 unsigned long stableL2 ; /* from IDI registry to WMP */
252 unsigned long tei ; /* from IDI registry to WMP */
253#define CRC4_MASK 0x00000003
254#define L1_TRISTATE_MASK 0x00000004
255#define WATCHDOG_MASK 0x00000008
256#define NO_ORDER_CHECK_MASK 0x00000010
257#define LOW_CHANNEL_MASK 0x00000020
258#define NO_HSCX30_MASK 0x00000040
259#define MODE_MASK 0x00000080
260#define SET_BOARD 0x00001000
261#define SET_CRC4 0x00030000
262#define SET_L1_TRISTATE 0x00040000
263#define SET_WATCHDOG 0x00080000
264#define SET_NO_ORDER_CHECK 0x00100000
265#define SET_LOW_CHANNEL 0x00200000
266#define SET_NO_HSCX30 0x00400000
267#define SET_MODE 0x00800000
268#define SET_PROTO 0x02000000
269#define SET_CARDTYPE 0x04000000
270#define SET_NT2 0x08000000
271#define SET_PERMANENT 0x10000000
272#define SET_STABLEL2 0x20000000
273#define SET_TEI 0x40000000
274#define SET_NUMBERLEN 0x80000000
275 unsigned long Flag ; /* |31-Type-16|15-Mask-0| */
276 unsigned long NumberLen ; /* reconfiguration: union is empty */
277 union {
278 struct { /* possible reconfiguration, but ... ; SET_BOARD */
279 unsigned long SerialNumber ;
280 char *pCardname ; /* di_defs.h: BOARD_NAME_LENGTH */
281 } board ;
282 struct { /* reset: need resources */
283 void * pRawResources ;
284 void * pXlatResources ;
285 } res ;
286 struct { /* reconfiguration: wizProto == PROTTYPE_RBSCAS */
287#define GLARE_RESOLVE_MASK 0x00000001
288#define DID_MASK 0x00000002
289#define BEARER_CAP_MASK 0x0000000c
290#define SET_GLARE_RESOLVE 0x00010000
291#define SET_DID 0x00020000
292#define SET_BEARER_CAP 0x000c0000
293 unsigned long Flag ; /* |31-Type-16|15-VALUE-0| */
294 unsigned short DigitTimeout ;
295 unsigned short AnswerDelay ;
296 } rbs ;
297 struct { /* reconfiguration: wizProto == PROTTYPE_QSIG */
298#define CALL_REF_LENGTH1_MASK 0x00000001
299#define BRI_CHANNEL_ID_MASK 0x00000002
300#define SET_CALL_REF_LENGTH 0x00010000
301#define SET_BRI_CHANNEL_ID 0x00020000
302 unsigned long Flag ; /* |31-Type-16|15-VALUE-0| */
303 } qsig ;
304 struct { /* reconfiguration: NumberLen != 0 */
305#define SET_SPID1 0x00010000
306#define SET_NUMBER1 0x00020000
307#define SET_SUBADDRESS1 0x00040000
308#define SET_SPID2 0x00100000
309#define SET_NUMBER2 0x00200000
310#define SET_SUBADDRESS2 0x00400000
311#define MASK_SET 0xffff0000
312 unsigned long Flag ; /* |31-Type-16|15-Channel-0| */
313 unsigned char *pBuffer ; /* number value */
314 } isdnNo ;
315 }
316parms
317;
318} isdnProps ;
319/*
320 * IDI_SYNC_REQ_PORTDRV_HOOK - signal plug/unplug (Award Cardware only)
321 */
322typedef void ( * PORTDRV_HOOK_CB) (void *Context, int Plug) ;
323typedef struct
324{ /* 'Req' and 'Rc' must be at the same place as in the ENTITY struct */
325 unsigned char Req; /* request (must be always 0) */
326 unsigned char Rc; /* return code (is the request) */
327 unsigned char Function; /* private function code */
328 unsigned char Flags; /* function refinements */
329 PORTDRV_HOOK_CB Callback; /* to be called on plug/unplug */
330 void *Context; /* context for callback */
331 unsigned long Info; /* more info if needed */
332} PORTDRV_HOOK ;
333/* Codes for the 'Rc' element in structure below. */
334#define SLI_INSTALL (0xA1)
335#define SLI_UNINSTALL (0xA2)
336typedef int ( * SLIENTRYPOINT)(void* p3SignalAPI, void* pContext);
337typedef struct
338{ /* 'Req' and 'Rc' must be at the same place as in the ENTITY struct */
339 unsigned char Req; /* request (must be always 0) */
340 unsigned char Rc; /* return code (is the request) */
341 unsigned char Function; /* private function code */
342 unsigned char Flags; /* function refinements */
343 SLIENTRYPOINT Callback; /* to be called on plug/unplug */
344 void *Context; /* context for callback */
345 unsigned long Info; /* more info if needed */
346} SLIENTRYPOINT_REQ ;
347/******************************************************************************/
348/*
349 * Definitions for DIVA USB
350 */
351typedef int ( * USB_SEND_REQ) (unsigned char PipeIndex, unsigned char Type,void *Data, int sizeData);
352typedef int ( * USB_START_DEV) (void *Adapter, void *Ipac) ;
353/* called from WDM */
354typedef void ( * USB_RECV_NOTIFY) (void *Ipac, void *msg) ;
355typedef void ( * USB_XMIT_NOTIFY) (void *Ipac, unsigned char PipeIndex) ;
356/******************************************************************************/
357/*
358 * Parameter description for synchronous requests.
359 *
360 * Sorry, must repeat some parts of di_defs.h here because
361 * they are not defined for all operating environments
362 */
363typedef union
364{ ENTITY Entity;
365 struct
366 { /* 'Req' and 'Rc' are at the same place as in the ENTITY struct */
367 unsigned char Req; /* request (must be always 0) */
368 unsigned char Rc; /* return code (is the request) */
369 } Request;
370 struct
371 { unsigned char Req; /* request (must be always 0) */
372 unsigned char Rc; /* return code (0x01) */
373 unsigned char name[BOARD_NAME_LENGTH];
374 } GetName;
375 struct
376 { unsigned char Req; /* request (must be always 0) */
377 unsigned char Rc; /* return code (0x02) */
378 unsigned long serial; /* serial number */
379 } GetSerial;
380 struct
381 { unsigned char Req; /* request (must be always 0) */
382 unsigned char Rc; /* return code (0x02) */
383 unsigned long lineIdx;/* line, 0 if card has only one */
384 } GetLineIdx;
385 struct
386 { unsigned char Req; /* request (must be always 0) */
387 unsigned char Rc; /* return code (0x02) */
388 unsigned long cardtype;/* card type */
389 } GetCardType;
390 struct
391 { unsigned short command;/* command = 0x0300 */
392 unsigned short dummy; /* not used */
393 IDI_CALL callback;/* routine to call back */
394 ENTITY *contxt; /* ptr to entity to use */
395 } PostCall;
396 struct
397 { unsigned char Req; /* request (must be always 0) */
398 unsigned char Rc; /* return code (0x04) */
399 unsigned char pcm[1]; /* buffer (a pc_maint struct) */
400 } GetXlog;
401 struct
402 { unsigned char Req; /* request (must be always 0) */
403 unsigned char Rc; /* return code (0x05) */
404 unsigned short features;/* feature defines see below */
405 } GetFeatures;
406 SERIAL_HOOK SerialHook;
407/* Added for DIVA USB */
408 struct
409 { unsigned char Req;
410 unsigned char Rc;
411 USB_SEND_REQ UsbSendRequest; /* function in Diva Usb WDM driver in usb_os.c, */
412 /* called from usb_drv.c to send a message to our device */
413 /* eg UsbSendRequest (USB_PIPE_SIGNAL, USB_IPAC_START, 0, 0) ; */
414 USB_RECV_NOTIFY usb_recv; /* called from usb_os.c to pass a received message and ptr to IPAC */
415 /* on to usb_drv.c by a call to usb_recv(). */
416 USB_XMIT_NOTIFY usb_xmit; /* called from usb_os.c in DivaUSB.sys WDM to indicate a completed transmit */
417 /* to usb_drv.c by a call to usb_xmit(). */
418 USB_START_DEV UsbStartDevice; /* Start the USB Device, in usb_os.c */
419 IDI_CALL callback; /* routine to call back */
420 ENTITY *contxt; /* ptr to entity to use */
421 void ** ipac_ptr; /* pointer to struct IPAC in VxD */
422 } Usb_Msg_old;
423/* message used by WDM and VXD to pass pointers of function and IPAC* */
424 struct
425 { unsigned char Req;
426 unsigned char Rc;
427 USB_SEND_REQ pUsbSendRequest;/* function in Diva Usb WDM driver in usb_os.c, */
428 /* called from usb_drv.c to send a message to our device */
429 /* eg UsbSendRequest (USB_PIPE_SIGNAL, USB_IPAC_START, 0, 0) ; */
430 USB_RECV_NOTIFY p_usb_recv; /* called from usb_os.c to pass a received message and ptr to IPAC */
431 /* on to usb_drv.c by a call to usb_recv(). */
432 USB_XMIT_NOTIFY p_usb_xmit; /* called from usb_os.c in DivaUSB.sys WDM to indicate a completed transmit */
433 /* to usb_drv.c by a call to usb_xmit().*/
434 void *ipac_ptr; /* &Diva.ipac pointer to struct IPAC in VxD */
435 } Usb_Msg;
436 PORTDRV_HOOK PortdrvHook;
437 SLIENTRYPOINT_REQ sliEntryPointReq;
438 struct {
439 unsigned char Req;
440 unsigned char Rc;
441 diva_xdi_stream_interface_t info;
442 } xdi_stream_info;
443 struct {
444 unsigned char Req;
445 unsigned char Rc;
446 diva_xdi_get_extended_xdi_features_t info;
447 } xdi_extended_features;
448 struct {
449 unsigned char Req;
450 unsigned char Rc;
451 diva_xdi_get_adapter_sdram_bar_t info;
452 } xdi_sdram_bar;
453 struct {
454 unsigned char Req;
455 unsigned char Rc;
456 diva_xdi_get_capi_parameters_t info;
457 } xdi_capi_prms;
458 struct {
459 ENTITY e;
460 diva_didd_adapter_notify_t info;
461 } didd_notify;
462 struct {
463 ENTITY e;
464 diva_didd_add_adapter_t info;
465 } didd_add_adapter;
466 struct {
467 ENTITY e;
468 diva_didd_remove_adapter_t info;
469 } didd_remove_adapter;
470 struct {
471 ENTITY e;
472 diva_didd_read_adapter_array_t info;
473 } didd_read_adapter_array;
474 struct {
475 ENTITY e;
476 diva_didd_get_cfg_lib_ifc_t info;
477 } didd_get_cfg_lib_ifc;
478 struct {
479 unsigned char Req;
480 unsigned char Rc;
481 diva_xdi_get_logical_adapter_number_s_t info;
482 } xdi_logical_adapter_number;
483 struct {
484 unsigned char Req;
485 unsigned char Rc;
486 diva_xdi_dma_descriptor_operation_t info;
487 } xdi_dma_descriptor_operation;
488} IDI_SYNC_REQ;
489/******************************************************************************/
490#endif /* __DIVA_SYNC__H */
diff --git a/drivers/isdn/hardware/eicon/dqueue.c b/drivers/isdn/hardware/eicon/dqueue.c
new file mode 100644
index 000000000000..982258225174
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/dqueue.c
@@ -0,0 +1,110 @@
1/* $Id: dqueue.c,v 1.5 2003/04/12 21:40:49 schindler Exp $
2 *
3 * Driver for Eicon DIVA Server ISDN cards.
4 * User Mode IDI Interface
5 *
6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 */
12
13#include "platform.h"
14#include "dqueue.h"
15
16int
17diva_data_q_init(diva_um_idi_data_queue_t * q,
18 int max_length, int max_segments)
19{
20 int i;
21
22 q->max_length = max_length;
23 q->segments = max_segments;
24
25 for (i = 0; i < q->segments; i++) {
26 q->data[i] = NULL;
27 q->length[i] = 0;
28 }
29 q->read = q->write = q->count = q->segment_pending = 0;
30
31 for (i = 0; i < q->segments; i++) {
32 if (!(q->data[i] = diva_os_malloc(0, q->max_length))) {
33 diva_data_q_finit(q);
34 return (-1);
35 }
36 }
37
38 return (0);
39}
40
41int diva_data_q_finit(diva_um_idi_data_queue_t * q)
42{
43 int i;
44
45 for (i = 0; i < q->segments; i++) {
46 if (q->data[i]) {
47 diva_os_free(0, q->data[i]);
48 }
49 q->data[i] = NULL;
50 q->length[i] = 0;
51 }
52 q->read = q->write = q->count = q->segment_pending = 0;
53
54 return (0);
55}
56
57int diva_data_q_get_max_length(const diva_um_idi_data_queue_t * q)
58{
59 return (q->max_length);
60}
61
62void *diva_data_q_get_segment4write(diva_um_idi_data_queue_t * q)
63{
64 if ((!q->segment_pending) && (q->count < q->segments)) {
65 q->segment_pending = 1;
66 return (q->data[q->write]);
67 }
68
69 return NULL;
70}
71
72void
73diva_data_q_ack_segment4write(diva_um_idi_data_queue_t * q, int length)
74{
75 if (q->segment_pending) {
76 q->length[q->write] = length;
77 q->count++;
78 q->write++;
79 if (q->write >= q->segments) {
80 q->write = 0;
81 }
82 q->segment_pending = 0;
83 }
84}
85
86const void *diva_data_q_get_segment4read(const diva_um_idi_data_queue_t *
87 q)
88{
89 if (q->count) {
90 return (q->data[q->read]);
91 }
92 return NULL;
93}
94
95int diva_data_q_get_segment_length(const diva_um_idi_data_queue_t * q)
96{
97 return (q->length[q->read]);
98}
99
100void diva_data_q_ack_segment4read(diva_um_idi_data_queue_t * q)
101{
102 if (q->count) {
103 q->length[q->read] = 0;
104 q->count--;
105 q->read++;
106 if (q->read >= q->segments) {
107 q->read = 0;
108 }
109 }
110}
diff --git a/drivers/isdn/hardware/eicon/dqueue.h b/drivers/isdn/hardware/eicon/dqueue.h
new file mode 100644
index 000000000000..72d21c967227
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/dqueue.h
@@ -0,0 +1,31 @@
1/* $Id: dqueue.h,v 1.1.2.2 2001/02/08 12:25:43 armin Exp $ */
2
3#ifndef _DIVA_USER_MODE_IDI_DATA_QUEUE_H__
4#define _DIVA_USER_MODE_IDI_DATA_QUEUE_H__
5
6#define DIVA_UM_IDI_MAX_MSGS 64
7
8typedef struct _diva_um_idi_data_queue {
9 int segments;
10 int max_length;
11 int read;
12 int write;
13 int count;
14 int segment_pending;
15 void *data[DIVA_UM_IDI_MAX_MSGS];
16 int length[DIVA_UM_IDI_MAX_MSGS];
17} diva_um_idi_data_queue_t;
18
19int diva_data_q_init(diva_um_idi_data_queue_t * q,
20 int max_length, int max_segments);
21int diva_data_q_finit(diva_um_idi_data_queue_t * q);
22int diva_data_q_get_max_length(const diva_um_idi_data_queue_t * q);
23void *diva_data_q_get_segment4write(diva_um_idi_data_queue_t * q);
24void diva_data_q_ack_segment4write(diva_um_idi_data_queue_t * q,
25 int length);
26const void *diva_data_q_get_segment4read(const diva_um_idi_data_queue_t *
27 q);
28int diva_data_q_get_segment_length(const diva_um_idi_data_queue_t * q);
29void diva_data_q_ack_segment4read(diva_um_idi_data_queue_t * q);
30
31#endif
diff --git a/drivers/isdn/hardware/eicon/dsp_defs.h b/drivers/isdn/hardware/eicon/dsp_defs.h
new file mode 100644
index 000000000000..b44950e06f32
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/dsp_defs.h
@@ -0,0 +1,304 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef DSP_DEFS_H_
27#define DSP_DEFS_H_
28#include "dspdids.h"
29/*---------------------------------------------------------------------------*/
30#define dsp_download_reserve_space(fp,length)
31/*****************************************************************************/
32/*
33 * OS file access abstraction layer
34 *
35 * I/O functions returns -1 on error, 0 on EOF
36 */
37#define OS_SEEK_SET 0
38#define OS_SEEK_CUR 1
39#define OS_SEEK_END 2
40struct _OsFileHandle_;
41typedef long ( * OsFileIo) (struct _OsFileHandle_ *handle,
42 void *buffer,
43 long size) ;
44typedef long ( * OsFileSeek)(struct _OsFileHandle_ *handle,
45 long position,
46 int mode) ;
47typedef long ( * OsCardLoad)(struct _OsFileHandle_ *handle,
48 long length,
49 void * *addr) ;
50typedef struct _OsFileHandle_
51{ void *sysFileDesc ;
52 unsigned long sysFileSize ;
53 OsFileIo sysFileRead ;
54 OsFileSeek sysFileSeek ;
55 void *sysLoadDesc ;
56 OsCardLoad sysCardLoad ;
57} OsFileHandle ;
58extern OsFileHandle *OsOpenFile (char *path_name) ;
59extern void OsCloseFile (OsFileHandle *fp) ;
60/*****************************************************************************/
61#define DSP_TELINDUS_FILE "dspdload.bin"
62/* special DSP file for BRI cards for Qsig and CornetN because of missing memory */
63#define DSP_QSIG_TELINDUS_FILE "dspdqsig.bin"
64#define DSP_MDM_TELINDUS_FILE "dspdvmdm.bin"
65#define DSP_FAX_TELINDUS_FILE "dspdvfax.bin"
66#define DSP_DIRECTORY_ENTRIES 64
67#define DSP_MEMORY_TYPE_EXTERNAL_DM 0
68#define DSP_MEMORY_TYPE_EXTERNAL_PM 1
69#define DSP_MEMORY_TYPE_INTERNAL_DM 2
70#define DSP_MEMORY_TYPE_INTERNAL_PM 3
71#define DSP_DOWNLOAD_FLAG_BOOTABLE 0x0001
72#define DSP_DOWNLOAD_FLAG_2181 0x0002
73#define DSP_DOWNLOAD_FLAG_TIMECRITICAL 0x0004
74#define DSP_DOWNLOAD_FLAG_COMPAND 0x0008
75#define DSP_MEMORY_BLOCK_COUNT 16
76#define DSP_SEGMENT_PM_FLAG 0x0001
77#define DSP_SEGMENT_SHARED_FLAG 0x0002
78#define DSP_SEGMENT_EXTERNAL_DM DSP_MEMORY_TYPE_EXTERNAL_DM
79#define DSP_SEGMENT_EXTERNAL_PM DSP_MEMORY_TYPE_EXTERNAL_PM
80#define DSP_SEGMENT_INTERNAL_DM DSP_MEMORY_TYPE_INTERNAL_DM
81#define DSP_SEGMENT_INTERNAL_PM DSP_MEMORY_TYPE_INTERNAL_PM
82#define DSP_SEGMENT_FIRST_RELOCATABLE 4
83#define DSP_DATA_BLOCK_PM_FLAG 0x0001
84#define DSP_DATA_BLOCK_DWORD_FLAG 0x0002
85#define DSP_DATA_BLOCK_RESOLVE_FLAG 0x0004
86#define DSP_RELOC_NONE 0x00
87#define DSP_RELOC_SEGMENT_MASK 0x3f
88#define DSP_RELOC_TYPE_MASK 0xc0
89#define DSP_RELOC_TYPE_0 0x00 /* relocation of address in DM word / high part of PM word */
90#define DSP_RELOC_TYPE_1 0x40 /* relocation of address in low part of PM data word */
91#define DSP_RELOC_TYPE_2 0x80 /* relocation of address in standard command */
92#define DSP_RELOC_TYPE_3 0xc0 /* relocation of address in call/jump on flag in */
93#define DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE 48
94#define DSP_COMBIFILE_FORMAT_VERSION_BCD 0x0100
95#define DSP_FILE_FORMAT_IDENTIFICATION_SIZE 48
96#define DSP_FILE_FORMAT_VERSION_BCD 0x0100
97typedef struct tag_dsp_combifile_header
98{
99 char format_identification[DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE];
100 word format_version_bcd;
101 word header_size;
102 word combifile_description_size;
103 word directory_entries;
104 word directory_size;
105 word download_count;
106 word usage_mask_size;
107} t_dsp_combifile_header;
108typedef struct tag_dsp_combifile_directory_entry
109{
110 word card_type_number;
111 word file_set_number;
112} t_dsp_combifile_directory_entry;
113typedef struct tag_dsp_file_header
114{
115 char format_identification[DSP_FILE_FORMAT_IDENTIFICATION_SIZE];
116 word format_version_bcd;
117 word download_id;
118 word download_flags;
119 word required_processing_power;
120 word interface_channel_count;
121 word header_size;
122 word download_description_size;
123 word memory_block_table_size;
124 word memory_block_count;
125 word segment_table_size;
126 word segment_count;
127 word symbol_table_size;
128 word symbol_count;
129 word total_data_size_dm;
130 word data_block_count_dm;
131 word total_data_size_pm;
132 word data_block_count_pm;
133} t_dsp_file_header;
134typedef struct tag_dsp_memory_block_desc
135{
136 word alias_memory_block;
137 word memory_type;
138 word address;
139 word size; /* DSP words */
140} t_dsp_memory_block_desc;
141typedef struct tag_dsp_segment_desc
142{
143 word memory_block;
144 word attributes;
145 word base;
146 word size;
147 word alignment; /* ==0 -> no other legal start address than base */
148} t_dsp_segment_desc;
149typedef struct tag_dsp_symbol_desc
150{
151 word symbol_id;
152 word segment;
153 word offset;
154 word size; /* DSP words */
155} t_dsp_symbol_desc;
156typedef struct tag_dsp_data_block_header
157{
158 word attributes;
159 word segment;
160 word offset;
161 word size; /* DSP words */
162} t_dsp_data_block_header;
163typedef struct tag_dsp_download_desc
164{
165 word download_id;
166 word download_flags;
167 word required_processing_power;
168 word interface_channel_count;
169 word excess_header_size;
170 word memory_block_count;
171 word segment_count;
172 word symbol_count;
173 word data_block_count_dm;
174 word data_block_count_pm;
175 byte * p_excess_header_data;
176 char * p_download_description;
177 t_dsp_memory_block_desc *p_memory_block_table;
178 t_dsp_segment_desc *p_segment_table;
179 t_dsp_symbol_desc *p_symbol_table;
180 word * p_data_blocks_dm;
181 word * p_data_blocks_pm;
182} t_dsp_desc;
183typedef struct tag_dsp_portable_download_desc /* be sure to keep native alignment for MAESTRA's */
184{
185 word download_id;
186 word download_flags;
187 word required_processing_power;
188 word interface_channel_count;
189 word excess_header_size;
190 word memory_block_count;
191 word segment_count;
192 word symbol_count;
193 word data_block_count_dm;
194 word data_block_count_pm;
195 dword p_excess_header_data;
196 dword p_download_description;
197 dword p_memory_block_table;
198 dword p_segment_table;
199 dword p_symbol_table;
200 dword p_data_blocks_dm;
201 dword p_data_blocks_pm;
202} t_dsp_portable_desc;
203#define DSP_DOWNLOAD_INDEX_KERNEL 0
204#define DSP30TX_DOWNLOAD_INDEX_KERNEL 1
205#define DSP30RX_DOWNLOAD_INDEX_KERNEL 2
206#define DSP_MAX_DOWNLOAD_COUNT 64
207#define DSP_DOWNLOAD_MAX_SEGMENTS 16
208#define DSP_UDATA_REQUEST_RECONFIGURE 0
209/*
210parameters:
211 <word> reconfigure delay (in 8kHz samples)
212 <word> reconfigure code
213 <byte> reconfigure hdlc preamble flags
214*/
215#define DSP_RECONFIGURE_TX_FLAG 0x8000
216#define DSP_RECONFIGURE_SHORT_TRAIN_FLAG 0x4000
217#define DSP_RECONFIGURE_ECHO_PROTECT_FLAG 0x2000
218#define DSP_RECONFIGURE_HDLC_FLAG 0x1000
219#define DSP_RECONFIGURE_SYNC_FLAG 0x0800
220#define DSP_RECONFIGURE_PROTOCOL_MASK 0x00ff
221#define DSP_RECONFIGURE_IDLE 0
222#define DSP_RECONFIGURE_V25 1
223#define DSP_RECONFIGURE_V21_CH2 2
224#define DSP_RECONFIGURE_V27_2400 3
225#define DSP_RECONFIGURE_V27_4800 4
226#define DSP_RECONFIGURE_V29_7200 5
227#define DSP_RECONFIGURE_V29_9600 6
228#define DSP_RECONFIGURE_V33_12000 7
229#define DSP_RECONFIGURE_V33_14400 8
230#define DSP_RECONFIGURE_V17_7200 9
231#define DSP_RECONFIGURE_V17_9600 10
232#define DSP_RECONFIGURE_V17_12000 11
233#define DSP_RECONFIGURE_V17_14400 12
234/*
235data indications if transparent framer
236 <byte> data 0
237 <byte> data 1
238 ...
239data indications if HDLC framer
240 <byte> data 0
241 <byte> data 1
242 ...
243 <byte> CRC 0
244 <byte> CRC 1
245 <byte> preamble flags
246*/
247#define DSP_UDATA_INDICATION_SYNC 0
248/*
249returns:
250 <word> time of sync (sampled from counter at 8kHz)
251*/
252#define DSP_UDATA_INDICATION_DCD_OFF 1
253/*
254returns:
255 <word> time of DCD off (sampled from counter at 8kHz)
256*/
257#define DSP_UDATA_INDICATION_DCD_ON 2
258/*
259returns:
260 <word> time of DCD on (sampled from counter at 8kHz)
261 <byte> connected norm
262 <word> connected options
263 <dword> connected speed (bit/s)
264*/
265#define DSP_UDATA_INDICATION_CTS_OFF 3
266/*
267returns:
268 <word> time of CTS off (sampled from counter at 8kHz)
269*/
270#define DSP_UDATA_INDICATION_CTS_ON 4
271/*
272returns:
273 <word> time of CTS on (sampled from counter at 8kHz)
274 <byte> connected norm
275 <word> connected options
276 <dword> connected speed (bit/s)
277*/
278#define DSP_CONNECTED_NORM_UNSPECIFIED 0
279#define DSP_CONNECTED_NORM_V21 1
280#define DSP_CONNECTED_NORM_V23 2
281#define DSP_CONNECTED_NORM_V22 3
282#define DSP_CONNECTED_NORM_V22_BIS 4
283#define DSP_CONNECTED_NORM_V32_BIS 5
284#define DSP_CONNECTED_NORM_V34 6
285#define DSP_CONNECTED_NORM_V8 7
286#define DSP_CONNECTED_NORM_BELL_212A 8
287#define DSP_CONNECTED_NORM_BELL_103 9
288#define DSP_CONNECTED_NORM_V29_LEASED_LINE 10
289#define DSP_CONNECTED_NORM_V33_LEASED_LINE 11
290#define DSP_CONNECTED_NORM_TFAST 12
291#define DSP_CONNECTED_NORM_V21_CH2 13
292#define DSP_CONNECTED_NORM_V27_TER 14
293#define DSP_CONNECTED_NORM_V29 15
294#define DSP_CONNECTED_NORM_V33 16
295#define DSP_CONNECTED_NORM_V17 17
296#define DSP_CONNECTED_OPTION_TRELLIS 0x0001
297/*---------------------------------------------------------------------------*/
298extern char *dsp_read_file (OsFileHandle *fp,
299 word card_type_number,
300 word *p_dsp_download_count,
301 t_dsp_desc *p_dsp_download_table,
302 t_dsp_portable_desc *p_dsp_portable_download_table) ;
303/*---------------------------------------------------------------------------*/
304#endif /* DSP_DEFS_H_ */
diff --git a/drivers/isdn/hardware/eicon/dsp_tst.h b/drivers/isdn/hardware/eicon/dsp_tst.h
new file mode 100644
index 000000000000..a6021e5b1ae7
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/dsp_tst.h
@@ -0,0 +1,47 @@
1/* $Id: dsp_tst.h,v 1.1.2.2 2001/02/08 12:25:43 armin Exp $ */
2
3#ifndef __DIVA_PRI_HOST_TEST_DSPS_H__
4#define __DIVA_PRI_HOST_TEST_DSPS_H__
5
6/*
7 DSP registers on maestra pri
8 */
9#define DSP1_PORT (0x00)
10#define DSP2_PORT (0x8)
11#define DSP3_PORT (0x800)
12#define DSP4_PORT (0x808)
13#define DSP5_PORT (0x810)
14#define DSP6_PORT (0x818)
15#define DSP7_PORT (0x820)
16#define DSP8_PORT (0x828)
17#define DSP9_PORT (0x830)
18#define DSP10_PORT (0x840)
19#define DSP11_PORT (0x848)
20#define DSP12_PORT (0x850)
21#define DSP13_PORT (0x858)
22#define DSP14_PORT (0x860)
23#define DSP15_PORT (0x868)
24#define DSP16_PORT (0x870)
25#define DSP17_PORT (0x1000)
26#define DSP18_PORT (0x1008)
27#define DSP19_PORT (0x1010)
28#define DSP20_PORT (0x1018)
29#define DSP21_PORT (0x1020)
30#define DSP22_PORT (0x1028)
31#define DSP23_PORT (0x1030)
32#define DSP24_PORT (0x1040)
33#define DSP25_PORT (0x1048)
34#define DSP26_PORT (0x1050)
35#define DSP27_PORT (0x1058)
36#define DSP28_PORT (0x1060)
37#define DSP29_PORT (0x1068)
38#define DSP30_PORT (0x1070)
39#define DSP_ADR_OFFS 0x80
40
41/*------------------------------------------------------------------
42 Dsp related definitions
43 ------------------------------------------------------------------ */
44#define DSP_SIGNATURE_PROBE_WORD 0x5a5a
45#define dsp_make_address_ex(pm,address) ((word)((pm) ? (address) : (address) + 0x4000))
46
47#endif
diff --git a/drivers/isdn/hardware/eicon/dspdids.h b/drivers/isdn/hardware/eicon/dspdids.h
new file mode 100644
index 000000000000..ebe131a53b9c
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/dspdids.h
@@ -0,0 +1,75 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef DSPDIDS_H_
27#define DSPDIDS_H_
28/*---------------------------------------------------------------------------*/
29#define DSP_DID_INVALID 0
30#define DSP_DID_DIVA 1
31#define DSP_DID_DIVA_PRO 2
32#define DSP_DID_DIVA_PRO_20 3
33#define DSP_DID_DIVA_PRO_PCCARD 4
34#define DSP_DID_DIVA_SERVER_BRI_1M 5
35#define DSP_DID_DIVA_SERVER_BRI_2M 6
36#define DSP_DID_DIVA_SERVER_PRI_2M_TX 7
37#define DSP_DID_DIVA_SERVER_PRI_2M_RX 8
38#define DSP_DID_DIVA_SERVER_PRI_30M 9
39#define DSP_DID_TASK_HSCX 100
40#define DSP_DID_TASK_HSCX_PRI_2M_TX 101
41#define DSP_DID_TASK_HSCX_PRI_2M_RX 102
42#define DSP_DID_TASK_V110KRNL 200
43#define DSP_DID_OVERLAY_V1100 201
44#define DSP_DID_OVERLAY_V1101 202
45#define DSP_DID_OVERLAY_V1102 203
46#define DSP_DID_OVERLAY_V1103 204
47#define DSP_DID_OVERLAY_V1104 205
48#define DSP_DID_OVERLAY_V1105 206
49#define DSP_DID_OVERLAY_V1106 207
50#define DSP_DID_OVERLAY_V1107 208
51#define DSP_DID_OVERLAY_V1108 209
52#define DSP_DID_OVERLAY_V1109 210
53#define DSP_DID_TASK_V110_PRI_2M_TX 220
54#define DSP_DID_TASK_V110_PRI_2M_RX 221
55#define DSP_DID_TASK_MODEM 300
56#define DSP_DID_TASK_FAX05 400
57#define DSP_DID_TASK_VOICE 500
58#define DSP_DID_TASK_TIKRNL81 600
59#define DSP_DID_OVERLAY_DIAL 601
60#define DSP_DID_OVERLAY_V22 602
61#define DSP_DID_OVERLAY_V32 603
62#define DSP_DID_OVERLAY_FSK 604
63#define DSP_DID_OVERLAY_FAX 605
64#define DSP_DID_OVERLAY_VXX 606
65#define DSP_DID_OVERLAY_V8 607
66#define DSP_DID_OVERLAY_INFO 608
67#define DSP_DID_OVERLAY_V34 609
68#define DSP_DID_OVERLAY_DFX 610
69#define DSP_DID_PARTIAL_OVERLAY_DIAL 611
70#define DSP_DID_PARTIAL_OVERLAY_FSK 612
71#define DSP_DID_PARTIAL_OVERLAY_FAX 613
72#define DSP_DID_TASK_TIKRNL05 700
73/*---------------------------------------------------------------------------*/
74#endif
75/*---------------------------------------------------------------------------*/
diff --git a/drivers/isdn/hardware/eicon/dsrv4bri.h b/drivers/isdn/hardware/eicon/dsrv4bri.h
new file mode 100644
index 000000000000..732d22dfe4a5
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/dsrv4bri.h
@@ -0,0 +1,40 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef __DIVA_XDI_DSRV_4_BRI_INC__
27#define __DIVA_XDI_DSRV_4_BRI_INC__
28/*
29 * Some special registers in the PLX 9054
30 */
31#define PLX9054_P2LDBELL 0x60
32#define PLX9054_L2PDBELL 0x64
33#define PLX9054_INTCSR 0x69
34#define PLX9054_INT_ENABLE 0x09
35#define PLX9054_SOFT_RESET 0x4000
36#define PLX9054_RELOAD_EEPROM 0x2000
37#define DIVA_4BRI_REVISION(__x__) (((__x__)->cardType == CARDTYPE_DIVASRV_Q_8M_V2_PCI) || ((__x__)->cardType == CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI) || ((__x__)->cardType == CARDTYPE_DIVASRV_B_2M_V2_PCI) || ((__x__)->cardType == CARDTYPE_DIVASRV_B_2F_PCI) || ((__x__)->cardType == CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI))
38void diva_os_set_qBri_functions (PISDN_ADAPTER IoAdapter);
39void diva_os_set_qBri2_functions (PISDN_ADAPTER IoAdapter);
40#endif
diff --git a/drivers/isdn/hardware/eicon/dsrv_bri.h b/drivers/isdn/hardware/eicon/dsrv_bri.h
new file mode 100644
index 000000000000..f38ebbe53332
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/dsrv_bri.h
@@ -0,0 +1,37 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef __DIVA_XDI_DSRV_BRI_INC__
27#define __DIVA_XDI_DSRV_BRI_INC__
28/*
29 Functions exported from os dependent part of
30 BRI card configuration and used in
31 OS independed part
32 */
33/*
34 Prepare OS dependent part of BRI functions
35 */
36void diva_os_prepare_maestra_functions (PISDN_ADAPTER IoAdapter);
37#endif
diff --git a/drivers/isdn/hardware/eicon/dsrv_pri.h b/drivers/isdn/hardware/eicon/dsrv_pri.h
new file mode 100644
index 000000000000..861182666c89
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/dsrv_pri.h
@@ -0,0 +1,38 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef __DIVA_XDI_DSRV_PRI_INC__
27#define __DIVA_XDI_DSRV_PRI_INC__
28/*
29 Functions exported from os dependent part of
30 PRI card configuration and used in
31 OS independed part
32 */
33/*
34 Prepare OS dependent part of PRI/PRI Rev.2 functions
35 */
36void diva_os_prepare_pri_functions (PISDN_ADAPTER IoAdapter);
37void diva_os_prepare_pri2_functions (PISDN_ADAPTER IoAdapter);
38#endif
diff --git a/drivers/isdn/hardware/eicon/entity.h b/drivers/isdn/hardware/eicon/entity.h
new file mode 100644
index 000000000000..16252cf164bb
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/entity.h
@@ -0,0 +1,28 @@
1/* $Id: entity.h,v 1.4 2004/03/21 17:26:01 armin Exp $ */
2
3#ifndef __DIVAS_USER_MODE_IDI_ENTITY__
4#define __DIVAS_USER_MODE_IDI_ENTITY__
5
6#define DIVA_UM_IDI_RC_PENDING 0x00000001
7#define DIVA_UM_IDI_REMOVE_PENDING 0x00000002
8#define DIVA_UM_IDI_TX_FLOW_CONTROL 0x00000004
9#define DIVA_UM_IDI_REMOVED 0x00000008
10#define DIVA_UM_IDI_ASSIGN_PENDING 0x00000010
11
12typedef struct _divas_um_idi_entity {
13 struct list_head link;
14 diva_um_idi_adapter_t* adapter; /* Back to adapter */
15 ENTITY e;
16 void* os_ref;
17 dword status;
18 void* os_context;
19 int rc_count;
20 diva_um_idi_data_queue_t data; /* definad by user 1 ... MAX */
21 diva_um_idi_data_queue_t rc; /* two entries */
22 BUFFERS XData;
23 BUFFERS RData;
24 byte buffer[2048+512];
25} divas_um_idi_entity_t;
26
27
28#endif
diff --git a/drivers/isdn/hardware/eicon/helpers.h b/drivers/isdn/hardware/eicon/helpers.h
new file mode 100644
index 000000000000..b2123119e430
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/helpers.h
@@ -0,0 +1,51 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef __DIVA_XDI_CARD_CONFIG_HELPERS_INC__
27#define __DIVA_XDI_CARD_CONFIG_HELPERS_INC__
28dword diva_get_protocol_file_features (byte* File,
29 int offset,
30 char *IdStringBuffer,
31 dword IdBufferSize);
32void diva_configure_protocol (PISDN_ADAPTER IoAdapter);
33/*
34 Low level file access system abstraction
35 */
36/* -------------------------------------------------------------------------
37 Access to single file
38 Return pointer to the image of the requested file,
39 write image length to 'FileLength'
40 ------------------------------------------------------------------------- */
41void *xdiLoadFile (char *FileName, dword *FileLength, unsigned long MaxLoadSize) ;
42/* -------------------------------------------------------------------------
43 Dependent on the protocol settings does read return pointer
44 to the image of appropriate protocol file
45 ------------------------------------------------------------------------- */
46void *xdiLoadArchive (PISDN_ADAPTER IoAdapter, dword *FileLength, unsigned long MaxLoadSize) ;
47/* --------------------------------------------------------------------------
48 Free all system resources accessed by xdiLoadFile and xdiLoadArchive
49 -------------------------------------------------------------------------- */
50void xdiFreeFile (void* handle);
51#endif
diff --git a/drivers/isdn/hardware/eicon/idifunc.c b/drivers/isdn/hardware/eicon/idifunc.c
new file mode 100644
index 000000000000..4cbc68cf4dba
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/idifunc.c
@@ -0,0 +1,267 @@
1/* $Id: idifunc.c,v 1.14.4.4 2004/08/28 20:03:53 armin Exp $
2 *
3 * Driver for Eicon DIVA Server ISDN cards.
4 * User Mode IDI Interface
5 *
6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 */
12
13#include "platform.h"
14#include "di_defs.h"
15#include "divasync.h"
16#include "um_xdi.h"
17#include "um_idi.h"
18
19#define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR)
20#define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG)
21
22extern char *DRIVERRELEASE_IDI;
23
24extern void DIVA_DIDD_Read(void *, int);
25extern int diva_user_mode_idi_create_adapter(const DESCRIPTOR *, int);
26extern void diva_user_mode_idi_remove_adapter(int);
27
28static dword notify_handle;
29static DESCRIPTOR DAdapter;
30static DESCRIPTOR MAdapter;
31
32static void no_printf(unsigned char *x, ...)
33{
34 /* dummy debug function */
35}
36
37#include "debuglib.c"
38
39/*
40 * stop debug
41 */
42static void stop_dbg(void)
43{
44 DbgDeregister();
45 memset(&MAdapter, 0, sizeof(MAdapter));
46 dprintf = no_printf;
47}
48
49typedef struct _udiva_card {
50 struct list_head list;
51 int Id;
52 DESCRIPTOR d;
53} udiva_card;
54
55static LIST_HEAD(cards);
56static diva_os_spin_lock_t ll_lock;
57
58/*
59 * find card in list
60 */
61static udiva_card *find_card_in_list(DESCRIPTOR * d)
62{
63 udiva_card *card;
64 struct list_head *tmp;
65 diva_os_spin_lock_magic_t old_irql;
66
67 diva_os_enter_spin_lock(&ll_lock, &old_irql, "find card");
68 list_for_each(tmp, &cards) {
69 card = list_entry(tmp, udiva_card, list);
70 if (card->d.request == d->request) {
71 diva_os_leave_spin_lock(&ll_lock, &old_irql,
72 "find card");
73 return (card);
74 }
75 }
76 diva_os_leave_spin_lock(&ll_lock, &old_irql, "find card");
77 return ((udiva_card *) NULL);
78}
79
80/*
81 * new card
82 */
83static void um_new_card(DESCRIPTOR * d)
84{
85 int adapter_nr = 0;
86 udiva_card *card = NULL;
87 IDI_SYNC_REQ sync_req;
88 diva_os_spin_lock_magic_t old_irql;
89
90 if (!(card = diva_os_malloc(0, sizeof(udiva_card)))) {
91 DBG_ERR(("cannot get buffer for card"));
92 return;
93 }
94 memcpy(&card->d, d, sizeof(DESCRIPTOR));
95 sync_req.xdi_logical_adapter_number.Req = 0;
96 sync_req.xdi_logical_adapter_number.Rc =
97 IDI_SYNC_REQ_XDI_GET_LOGICAL_ADAPTER_NUMBER;
98 card->d.request((ENTITY *) & sync_req);
99 adapter_nr =
100 sync_req.xdi_logical_adapter_number.info.logical_adapter_number;
101 card->Id = adapter_nr;
102 if (!(diva_user_mode_idi_create_adapter(d, adapter_nr))) {
103 diva_os_enter_spin_lock(&ll_lock, &old_irql, "add card");
104 list_add_tail(&card->list, &cards);
105 diva_os_leave_spin_lock(&ll_lock, &old_irql, "add card");
106 } else {
107 DBG_ERR(("could not create user mode idi card %d",
108 adapter_nr));
109 }
110}
111
112/*
113 * remove card
114 */
115static void um_remove_card(DESCRIPTOR * d)
116{
117 diva_os_spin_lock_magic_t old_irql;
118 udiva_card *card = NULL;
119
120 if (!(card = find_card_in_list(d))) {
121 DBG_ERR(("cannot find card to remove"));
122 return;
123 }
124 diva_user_mode_idi_remove_adapter(card->Id);
125 diva_os_enter_spin_lock(&ll_lock, &old_irql, "remove card");
126 list_del(&card->list);
127 diva_os_leave_spin_lock(&ll_lock, &old_irql, "remove card");
128 DBG_LOG(("idi proc entry removed for card %d", card->Id));
129 diva_os_free(0, card);
130}
131
132/*
133 * remove all adapter
134 */
135static void DIVA_EXIT_FUNCTION remove_all_idi_proc(void)
136{
137 udiva_card *card;
138 diva_os_spin_lock_magic_t old_irql;
139
140rescan:
141 diva_os_enter_spin_lock(&ll_lock, &old_irql, "remove all");
142 if (!list_empty(&cards)) {
143 card = list_entry(cards.next, udiva_card, list);
144 list_del(&card->list);
145 diva_os_leave_spin_lock(&ll_lock, &old_irql, "remove all");
146 diva_user_mode_idi_remove_adapter(card->Id);
147 diva_os_free(0, card);
148 goto rescan;
149 }
150 diva_os_leave_spin_lock(&ll_lock, &old_irql, "remove all");
151}
152
153/*
154 * DIDD notify callback
155 */
156static void *didd_callback(void *context, DESCRIPTOR * adapter,
157 int removal)
158{
159 if (adapter->type == IDI_DADAPTER) {
160 DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."));
161 return (NULL);
162 } else if (adapter->type == IDI_DIMAINT) {
163 if (removal) {
164 stop_dbg();
165 } else {
166 memcpy(&MAdapter, adapter, sizeof(MAdapter));
167 dprintf = (DIVA_DI_PRINTF) MAdapter.request;
168 DbgRegister("User IDI", DRIVERRELEASE_IDI, DBG_DEFAULT);
169 }
170 } else if ((adapter->type > 0) && (adapter->type < 16)) { /* IDI Adapter */
171 if (removal) {
172 um_remove_card(adapter);
173 } else {
174 um_new_card(adapter);
175 }
176 }
177 return (NULL);
178}
179
180/*
181 * connect DIDD
182 */
183static int DIVA_INIT_FUNCTION connect_didd(void)
184{
185 int x = 0;
186 int dadapter = 0;
187 IDI_SYNC_REQ req;
188 DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
189
190 DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
191
192 for (x = 0; x < MAX_DESCRIPTORS; x++) {
193 if (DIDD_Table[x].type == IDI_DADAPTER) { /* DADAPTER found */
194 dadapter = 1;
195 memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
196 req.didd_notify.e.Req = 0;
197 req.didd_notify.e.Rc =
198 IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
199 req.didd_notify.info.callback = (void *)didd_callback;
200 req.didd_notify.info.context = NULL;
201 DAdapter.request((ENTITY *) & req);
202 if (req.didd_notify.e.Rc != 0xff) {
203 stop_dbg();
204 return (0);
205 }
206 notify_handle = req.didd_notify.info.handle;
207 } else if (DIDD_Table[x].type == IDI_DIMAINT) { /* MAINT found */
208 memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter));
209 dprintf = (DIVA_DI_PRINTF) MAdapter.request;
210 DbgRegister("User IDI", DRIVERRELEASE_IDI, DBG_DEFAULT);
211 } else if ((DIDD_Table[x].type > 0)
212 && (DIDD_Table[x].type < 16)) { /* IDI Adapter found */
213 um_new_card(&DIDD_Table[x]);
214 }
215 }
216
217 if (!dadapter) {
218 stop_dbg();
219 }
220
221 return (dadapter);
222}
223
224/*
225 * Disconnect from DIDD
226 */
227static void DIVA_EXIT_FUNCTION disconnect_didd(void)
228{
229 IDI_SYNC_REQ req;
230
231 stop_dbg();
232
233 req.didd_notify.e.Req = 0;
234 req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
235 req.didd_notify.info.handle = notify_handle;
236 DAdapter.request((ENTITY *) & req);
237}
238
239/*
240 * init
241 */
242int DIVA_INIT_FUNCTION idifunc_init(void)
243{
244 diva_os_initialize_spin_lock(&ll_lock, "idifunc");
245
246 if (diva_user_mode_idi_init()) {
247 DBG_ERR(("init: init failed."));
248 return (0);
249 }
250
251 if (!connect_didd()) {
252 diva_user_mode_idi_finit();
253 DBG_ERR(("init: failed to connect to DIDD."));
254 return (0);
255 }
256 return (1);
257}
258
259/*
260 * finit
261 */
262void DIVA_EXIT_FUNCTION idifunc_finit(void)
263{
264 diva_user_mode_idi_finit();
265 disconnect_didd();
266 remove_all_idi_proc();
267}
diff --git a/drivers/isdn/hardware/eicon/io.c b/drivers/isdn/hardware/eicon/io.c
new file mode 100644
index 000000000000..4a27e230b0a5
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/io.c
@@ -0,0 +1,852 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#include "platform.h"
27#include "di_defs.h"
28#include "pc.h"
29#include "pr_pc.h"
30#include "divasync.h"
31#define MIPS_SCOM
32#include "pkmaint.h" /* pc_main.h, packed in os-dependent fashion */
33#include "di.h"
34#include "mi_pc.h"
35#include "io.h"
36extern ADAPTER * adapter[MAX_ADAPTER];
37extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER];
38void request (PISDN_ADAPTER, ENTITY *);
39static void pcm_req (PISDN_ADAPTER, ENTITY *);
40/* --------------------------------------------------------------------------
41 local functions
42 -------------------------------------------------------------------------- */
43#define ReqFunc(N) \
44static void Request##N(ENTITY *e) \
45{ if ( IoAdapters[N] ) (* IoAdapters[N]->DIRequest)(IoAdapters[N], e) ; }
46ReqFunc(0)
47ReqFunc(1)
48ReqFunc(2)
49ReqFunc(3)
50ReqFunc(4)
51ReqFunc(5)
52ReqFunc(6)
53ReqFunc(7)
54ReqFunc(8)
55ReqFunc(9)
56ReqFunc(10)
57ReqFunc(11)
58ReqFunc(12)
59ReqFunc(13)
60ReqFunc(14)
61ReqFunc(15)
62IDI_CALL Requests[MAX_ADAPTER] =
63{ &Request0, &Request1, &Request2, &Request3,
64 &Request4, &Request5, &Request6, &Request7,
65 &Request8, &Request9, &Request10, &Request11,
66 &Request12, &Request13, &Request14, &Request15
67};
68/*****************************************************************************/
69/*
70 This array should indicate all new services, that this version of XDI
71 is able to provide to his clients
72 */
73static byte extended_xdi_features[DIVA_XDI_EXTENDED_FEATURES_MAX_SZ+1] = {
74 (DIVA_XDI_EXTENDED_FEATURES_VALID |
75 DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR |
76 DIVA_XDI_EXTENDED_FEATURE_CAPI_PRMS |
77#if defined(DIVA_IDI_RX_DMA)
78 DIVA_XDI_EXTENDED_FEATURE_CMA |
79 DIVA_XDI_EXTENDED_FEATURE_RX_DMA |
80 DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA |
81#endif
82 DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC),
83 0
84};
85/*****************************************************************************/
86void
87dump_xlog_buffer (PISDN_ADAPTER IoAdapter, Xdesc *xlogDesc)
88{
89 dword logLen ;
90 word *Xlog = xlogDesc->buf ;
91 word logCnt = xlogDesc->cnt ;
92 word logOut = xlogDesc->out / sizeof(*Xlog) ;
93 DBG_FTL(("%s: ************* XLOG recovery (%d) *************",
94 &IoAdapter->Name[0], (int)logCnt))
95 DBG_FTL(("Microcode: %s", &IoAdapter->ProtocolIdString[0]))
96 for ( ; logCnt > 0 ; --logCnt )
97 {
98 if ( !GET_WORD(&Xlog[logOut]) )
99 {
100 if ( --logCnt == 0 )
101 break ;
102 logOut = 0 ;
103 }
104 if ( GET_WORD(&Xlog[logOut]) <= (logOut * sizeof(*Xlog)) )
105 {
106 if ( logCnt > 2 )
107 {
108 DBG_FTL(("Possibly corrupted XLOG: %d entries left",
109 (int)logCnt))
110 }
111 break ;
112 }
113 logLen = (dword)(GET_WORD(&Xlog[logOut]) - (logOut * sizeof(*Xlog))) ;
114 DBG_FTL_MXLOG(( (char *)&Xlog[logOut + 1], (dword)(logLen - 2) ))
115 logOut = (GET_WORD(&Xlog[logOut]) + 1) / sizeof(*Xlog) ;
116 }
117 DBG_FTL(("%s: ***************** end of XLOG *****************",
118 &IoAdapter->Name[0]))
119}
120/*****************************************************************************/
121#if defined(XDI_USE_XLOG)
122static char *(ExceptionCauseTable[]) =
123{
124 "Interrupt",
125 "TLB mod /IBOUND",
126 "TLB load /DBOUND",
127 "TLB store",
128 "Address error load",
129 "Address error store",
130 "Instruction load bus error",
131 "Data load/store bus error",
132 "Syscall",
133 "Breakpoint",
134 "Reverd instruction",
135 "Coprocessor unusable",
136 "Overflow",
137 "TRAP",
138 "VCEI",
139 "Floating Point Exception",
140 "CP2",
141 "Reserved 17",
142 "Reserved 18",
143 "Reserved 19",
144 "Reserved 20",
145 "Reserved 21",
146 "Reserved 22",
147 "WATCH",
148 "Reserved 24",
149 "Reserved 25",
150 "Reserved 26",
151 "Reserved 27",
152 "Reserved 28",
153 "Reserved 29",
154 "Reserved 30",
155 "VCED"
156} ;
157#endif
158void
159dump_trap_frame (PISDN_ADAPTER IoAdapter, byte __iomem *exceptionFrame)
160{
161 MP_XCPTC __iomem *xcept = (MP_XCPTC __iomem *)exceptionFrame ;
162 dword __iomem *regs;
163 regs = &xcept->regs[0] ;
164 DBG_FTL(("%s: ***************** CPU TRAPPED *****************",
165 &IoAdapter->Name[0]))
166 DBG_FTL(("Microcode: %s", &IoAdapter->ProtocolIdString[0]))
167 DBG_FTL(("Cause: %s",
168 ExceptionCauseTable[(READ_DWORD(&xcept->cr) & 0x0000007c) >> 2]))
169 DBG_FTL(("sr 0x%08x cr 0x%08x epc 0x%08x vaddr 0x%08x",
170 READ_DWORD(&xcept->sr), READ_DWORD(&xcept->cr),
171 READ_DWORD(&xcept->epc), READ_DWORD(&xcept->vaddr)))
172 DBG_FTL(("zero 0x%08x at 0x%08x v0 0x%08x v1 0x%08x",
173 READ_DWORD(&regs[ 0]), READ_DWORD(&regs[ 1]),
174 READ_DWORD(&regs[ 2]), READ_DWORD(&regs[ 3])))
175 DBG_FTL(("a0 0x%08x a1 0x%08x a2 0x%08x a3 0x%08x",
176 READ_DWORD(&regs[ 4]), READ_DWORD(&regs[ 5]),
177 READ_DWORD(&regs[ 6]), READ_DWORD(&regs[ 7])))
178 DBG_FTL(("t0 0x%08x t1 0x%08x t2 0x%08x t3 0x%08x",
179 READ_DWORD(&regs[ 8]), READ_DWORD(&regs[ 9]),
180 READ_DWORD(&regs[10]), READ_DWORD(&regs[11])))
181 DBG_FTL(("t4 0x%08x t5 0x%08x t6 0x%08x t7 0x%08x",
182 READ_DWORD(&regs[12]), READ_DWORD(&regs[13]),
183 READ_DWORD(&regs[14]), READ_DWORD(&regs[15])))
184 DBG_FTL(("s0 0x%08x s1 0x%08x s2 0x%08x s3 0x%08x",
185 READ_DWORD(&regs[16]), READ_DWORD(&regs[17]),
186 READ_DWORD(&regs[18]), READ_DWORD(&regs[19])))
187 DBG_FTL(("s4 0x%08x s5 0x%08x s6 0x%08x s7 0x%08x",
188 READ_DWORD(&regs[20]), READ_DWORD(&regs[21]),
189 READ_DWORD(&regs[22]), READ_DWORD(&regs[23])))
190 DBG_FTL(("t8 0x%08x t9 0x%08x k0 0x%08x k1 0x%08x",
191 READ_DWORD(&regs[24]), READ_DWORD(&regs[25]),
192 READ_DWORD(&regs[26]), READ_DWORD(&regs[27])))
193 DBG_FTL(("gp 0x%08x sp 0x%08x s8 0x%08x ra 0x%08x",
194 READ_DWORD(&regs[28]), READ_DWORD(&regs[29]),
195 READ_DWORD(&regs[30]), READ_DWORD(&regs[31])))
196 DBG_FTL(("md 0x%08x|%08x resvd 0x%08x class 0x%08x",
197 READ_DWORD(&xcept->mdhi), READ_DWORD(&xcept->mdlo),
198 READ_DWORD(&xcept->reseverd), READ_DWORD(&xcept->xclass)))
199}
200/* --------------------------------------------------------------------------
201 Real XDI Request function
202 -------------------------------------------------------------------------- */
203void request(PISDN_ADAPTER IoAdapter, ENTITY * e)
204{
205 byte i;
206 diva_os_spin_lock_magic_t irql;
207/*
208 * if the Req field in the entity structure is 0,
209 * we treat this request as a special function call
210 */
211 if ( !e->Req )
212 {
213 IDI_SYNC_REQ *syncReq = (IDI_SYNC_REQ *)e ;
214 switch (e->Rc)
215 {
216#if defined(DIVA_IDI_RX_DMA)
217 case IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION: {
218 diva_xdi_dma_descriptor_operation_t* pI = \
219 &syncReq->xdi_dma_descriptor_operation.info;
220 if (!IoAdapter->dma_map) {
221 pI->operation = -1;
222 pI->descriptor_number = -1;
223 return;
224 }
225 diva_os_enter_spin_lock (&IoAdapter->data_spin_lock, &irql, "dma_op");
226 if (pI->operation == IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC) {
227 pI->descriptor_number = diva_alloc_dma_map_entry (\
228 (struct _diva_dma_map_entry*)IoAdapter->dma_map);
229 if (pI->descriptor_number >= 0) {
230 dword dma_magic;
231 void* local_addr;
232 diva_get_dma_map_entry (\
233 (struct _diva_dma_map_entry*)IoAdapter->dma_map,
234 pI->descriptor_number,
235 &local_addr, &dma_magic);
236 pI->descriptor_address = local_addr;
237 pI->descriptor_magic = dma_magic;
238 pI->operation = 0;
239 } else {
240 pI->operation = -1;
241 }
242 } else if ((pI->operation == IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE) &&
243 (pI->descriptor_number >= 0)) {
244 diva_free_dma_map_entry((struct _diva_dma_map_entry*)IoAdapter->dma_map,
245 pI->descriptor_number);
246 pI->descriptor_number = -1;
247 pI->operation = 0;
248 } else {
249 pI->descriptor_number = -1;
250 pI->operation = -1;
251 }
252 diva_os_leave_spin_lock (&IoAdapter->data_spin_lock, &irql, "dma_op");
253 } return;
254#endif
255 case IDI_SYNC_REQ_XDI_GET_LOGICAL_ADAPTER_NUMBER: {
256 diva_xdi_get_logical_adapter_number_s_t *pI = \
257 &syncReq->xdi_logical_adapter_number.info;
258 pI->logical_adapter_number = IoAdapter->ANum;
259 pI->controller = IoAdapter->ControllerNumber;
260 pI->total_controllers = IoAdapter->Properties.Adapters;
261 } return;
262 case IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS: {
263 diva_xdi_get_capi_parameters_t prms, *pI = &syncReq->xdi_capi_prms.info;
264 memset (&prms, 0x00, sizeof(prms));
265 prms.structure_length = MIN(sizeof(prms), pI->structure_length);
266 memset (pI, 0x00, pI->structure_length);
267 prms.flag_dynamic_l1_down = (IoAdapter->capi_cfg.cfg_1 & \
268 DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ? 1 : 0;
269 prms.group_optimization_enabled = (IoAdapter->capi_cfg.cfg_1 & \
270 DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON) ? 1 : 0;
271 memcpy (pI, &prms, prms.structure_length);
272 } return;
273 case IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR:
274 syncReq->xdi_sdram_bar.info.bar = IoAdapter->sdram_bar;
275 return;
276 case IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES: {
277 dword i;
278 diva_xdi_get_extended_xdi_features_t* pI =\
279 &syncReq->xdi_extended_features.info;
280 pI->buffer_length_in_bytes &= ~0x80000000;
281 if (pI->buffer_length_in_bytes && pI->features) {
282 memset (pI->features, 0x00, pI->buffer_length_in_bytes);
283 }
284 for (i = 0; ((pI->features) && (i < pI->buffer_length_in_bytes) &&
285 (i < DIVA_XDI_EXTENDED_FEATURES_MAX_SZ)); i++) {
286 pI->features[i] = extended_xdi_features[i];
287 }
288 if ((pI->buffer_length_in_bytes < DIVA_XDI_EXTENDED_FEATURES_MAX_SZ) ||
289 (!pI->features)) {
290 pI->buffer_length_in_bytes =\
291 (0x80000000 | DIVA_XDI_EXTENDED_FEATURES_MAX_SZ);
292 }
293 } return;
294 case IDI_SYNC_REQ_XDI_GET_STREAM:
295 if (IoAdapter) {
296 diva_xdi_provide_istream_info (&IoAdapter->a,
297 &syncReq->xdi_stream_info.info);
298 } else {
299 syncReq->xdi_stream_info.info.provided_service = 0;
300 }
301 return;
302 case IDI_SYNC_REQ_GET_NAME:
303 if ( IoAdapter )
304 {
305 strcpy (&syncReq->GetName.name[0], IoAdapter->Name) ;
306 DBG_TRC(("xdi: Adapter %d / Name '%s'",
307 IoAdapter->ANum, IoAdapter->Name))
308 return ;
309 }
310 syncReq->GetName.name[0] = '\0' ;
311 break ;
312 case IDI_SYNC_REQ_GET_SERIAL:
313 if ( IoAdapter )
314 {
315 syncReq->GetSerial.serial = IoAdapter->serialNo ;
316 DBG_TRC(("xdi: Adapter %d / SerialNo %ld",
317 IoAdapter->ANum, IoAdapter->serialNo))
318 return ;
319 }
320 syncReq->GetSerial.serial = 0 ;
321 break ;
322 case IDI_SYNC_REQ_GET_CARDTYPE:
323 if ( IoAdapter )
324 {
325 syncReq->GetCardType.cardtype = IoAdapter->cardType ;
326 DBG_TRC(("xdi: Adapter %d / CardType %ld",
327 IoAdapter->ANum, IoAdapter->cardType))
328 return ;
329 }
330 syncReq->GetCardType.cardtype = 0 ;
331 break ;
332 case IDI_SYNC_REQ_GET_XLOG:
333 if ( IoAdapter )
334 {
335 pcm_req (IoAdapter, e) ;
336 return ;
337 }
338 e->Ind = 0 ;
339 break ;
340 case IDI_SYNC_REQ_GET_DBG_XLOG:
341 if ( IoAdapter )
342 {
343 pcm_req (IoAdapter, e) ;
344 return ;
345 }
346 e->Ind = 0 ;
347 break ;
348 case IDI_SYNC_REQ_GET_FEATURES:
349 if ( IoAdapter )
350 {
351 syncReq->GetFeatures.features =
352 (unsigned short)IoAdapter->features ;
353 return ;
354 }
355 syncReq->GetFeatures.features = 0 ;
356 break ;
357 case IDI_SYNC_REQ_PORTDRV_HOOK:
358 if ( IoAdapter )
359 {
360 DBG_TRC(("Xdi:IDI_SYNC_REQ_PORTDRV_HOOK - ignored"))
361 return ;
362 }
363 break;
364 }
365 if ( IoAdapter )
366 {
367 return ;
368 }
369 }
370 DBG_TRC(("xdi: Id 0x%x / Req 0x%x / Rc 0x%x", e->Id, e->Req, e->Rc))
371 if ( !IoAdapter )
372 {
373 DBG_FTL(("xdi: uninitialized Adapter used - ignore request"))
374 return ;
375 }
376 diva_os_enter_spin_lock (&IoAdapter->data_spin_lock, &irql, "data_req");
377/*
378 * assign an entity
379 */
380 if ( !(e->Id &0x1f) )
381 {
382 if ( IoAdapter->e_count >= IoAdapter->e_max )
383 {
384 DBG_FTL(("xdi: all Ids in use (max=%d) --> Req ignored",
385 IoAdapter->e_max))
386 diva_os_leave_spin_lock (&IoAdapter->data_spin_lock, &irql, "data_req");
387 return ;
388 }
389/*
390 * find a new free id
391 */
392 for ( i = 1 ; IoAdapter->e_tbl[i].e ; ++i ) ;
393 IoAdapter->e_tbl[i].e = e ;
394 IoAdapter->e_count++ ;
395 e->No = (byte)i ;
396 e->More = 0 ;
397 e->RCurrent = 0xff ;
398 }
399 else
400 {
401 i = e->No ;
402 }
403/*
404 * if the entity is still busy, ignore the request call
405 */
406 if ( e->More & XBUSY )
407 {
408 DBG_FTL(("xdi: Id 0x%x busy --> Req 0x%x ignored", e->Id, e->Req))
409 if ( !IoAdapter->trapped && IoAdapter->trapFnc )
410 {
411 IoAdapter->trapFnc (IoAdapter) ;
412 /*
413 Firs trap, also notify user if supported
414 */
415 if (IoAdapter->trapped && IoAdapter->os_trap_nfy_Fnc) {
416 (*(IoAdapter->os_trap_nfy_Fnc))(IoAdapter, IoAdapter->ANum);
417 }
418 }
419 diva_os_leave_spin_lock (&IoAdapter->data_spin_lock, &irql, "data_req");
420 return ;
421 }
422/*
423 * initialize transmit status variables
424 */
425 e->More |= XBUSY ;
426 e->More &= ~XMOREF ;
427 e->XCurrent = 0 ;
428 e->XOffset = 0 ;
429/*
430 * queue this entity in the adapter request queue
431 */
432 IoAdapter->e_tbl[i].next = 0 ;
433 if ( IoAdapter->head )
434 {
435 IoAdapter->e_tbl[IoAdapter->tail].next = i ;
436 IoAdapter->tail = i ;
437 }
438 else
439 {
440 IoAdapter->head = i ;
441 IoAdapter->tail = i ;
442 }
443/*
444 * queue the DPC to process the request
445 */
446 diva_os_schedule_soft_isr (&IoAdapter->req_soft_isr);
447 diva_os_leave_spin_lock (&IoAdapter->data_spin_lock, &irql, "data_req");
448}
449/* ---------------------------------------------------------------------
450 Main DPC routine
451 --------------------------------------------------------------------- */
452void DIDpcRoutine (struct _diva_os_soft_isr* psoft_isr, void* Context) {
453 PISDN_ADAPTER IoAdapter = (PISDN_ADAPTER)Context ;
454 ADAPTER* a = &IoAdapter->a ;
455 diva_os_atomic_t* pin_dpc = &IoAdapter->in_dpc;
456 if (diva_os_atomic_increment (pin_dpc) == 1) {
457 do {
458 if ( IoAdapter->tst_irq (a) )
459 {
460 if ( !IoAdapter->Unavailable )
461 IoAdapter->dpc (a) ;
462 IoAdapter->clr_irq (a) ;
463 }
464 IoAdapter->out (a) ;
465 } while (diva_os_atomic_decrement (pin_dpc) > 0);
466 /* ----------------------------------------------------------------
467 Look for XLOG request (cards with indirect addressing)
468 ---------------------------------------------------------------- */
469 if (IoAdapter->pcm_pending) {
470 struct pc_maint *pcm;
471 diva_os_spin_lock_magic_t OldIrql ;
472 diva_os_enter_spin_lock (&IoAdapter->data_spin_lock,
473 &OldIrql,
474 "data_dpc");
475 pcm = (struct pc_maint *)IoAdapter->pcm_data;
476 switch (IoAdapter->pcm_pending) {
477 case 1: /* ask card for XLOG */
478 a->ram_out (a, &IoAdapter->pcm->rc, 0) ;
479 a->ram_out (a, &IoAdapter->pcm->req, pcm->req) ;
480 IoAdapter->pcm_pending = 2;
481 break;
482 case 2: /* Try to get XLOG from the card */
483 if ((int)(a->ram_in (a, &IoAdapter->pcm->rc))) {
484 a->ram_in_buffer (a, IoAdapter->pcm, pcm, sizeof(*pcm)) ;
485 IoAdapter->pcm_pending = 3;
486 }
487 break;
488 case 3: /* let XDI recovery XLOG */
489 break;
490 }
491 diva_os_leave_spin_lock (&IoAdapter->data_spin_lock,
492 &OldIrql,
493 "data_dpc");
494 }
495 /* ---------------------------------------------------------------- */
496 }
497}
498/* --------------------------------------------------------------------------
499 XLOG interface
500 -------------------------------------------------------------------------- */
501static void
502pcm_req (PISDN_ADAPTER IoAdapter, ENTITY *e)
503{
504 diva_os_spin_lock_magic_t OldIrql ;
505 int i, rc ;
506 ADAPTER *a = &IoAdapter->a ;
507 struct pc_maint *pcm = (struct pc_maint *)&e->Ind ;
508/*
509 * special handling of I/O based card interface
510 * the memory access isn't an atomic operation !
511 */
512 if ( IoAdapter->Properties.Card == CARD_MAE )
513 {
514 diva_os_enter_spin_lock (&IoAdapter->data_spin_lock,
515 &OldIrql,
516 "data_pcm_1");
517 IoAdapter->pcm_data = (void *)pcm;
518 IoAdapter->pcm_pending = 1;
519 diva_os_schedule_soft_isr (&IoAdapter->req_soft_isr);
520 diva_os_leave_spin_lock (&IoAdapter->data_spin_lock,
521 &OldIrql,
522 "data_pcm_1");
523 for ( rc = 0, i = (IoAdapter->trapped ? 3000 : 250) ; !rc && (i > 0) ; --i )
524 {
525 diva_os_sleep (1) ;
526 if (IoAdapter->pcm_pending == 3) {
527 diva_os_enter_spin_lock (&IoAdapter->data_spin_lock,
528 &OldIrql,
529 "data_pcm_3");
530 IoAdapter->pcm_pending = 0;
531 IoAdapter->pcm_data = NULL ;
532 diva_os_leave_spin_lock (&IoAdapter->data_spin_lock,
533 &OldIrql,
534 "data_pcm_3");
535 return ;
536 }
537 diva_os_enter_spin_lock (&IoAdapter->data_spin_lock,
538 &OldIrql,
539 "data_pcm_2");
540 diva_os_schedule_soft_isr (&IoAdapter->req_soft_isr);
541 diva_os_leave_spin_lock (&IoAdapter->data_spin_lock,
542 &OldIrql,
543 "data_pcm_2");
544 }
545 diva_os_enter_spin_lock (&IoAdapter->data_spin_lock,
546 &OldIrql,
547 "data_pcm_4");
548 IoAdapter->pcm_pending = 0;
549 IoAdapter->pcm_data = NULL ;
550 diva_os_leave_spin_lock (&IoAdapter->data_spin_lock,
551 &OldIrql,
552 "data_pcm_4");
553 goto Trapped ;
554 }
555/*
556 * memory based shared ram is accessible from different
557 * processors without disturbing concurrent processes.
558 */
559 a->ram_out (a, &IoAdapter->pcm->rc, 0) ;
560 a->ram_out (a, &IoAdapter->pcm->req, pcm->req) ;
561 for ( i = (IoAdapter->trapped ? 3000 : 250) ; --i > 0 ; )
562 {
563 diva_os_sleep (1) ;
564 rc = (int)(a->ram_in (a, &IoAdapter->pcm->rc)) ;
565 if ( rc )
566 {
567 a->ram_in_buffer (a, IoAdapter->pcm, pcm, sizeof(*pcm)) ;
568 return ;
569 }
570 }
571Trapped:
572 if ( IoAdapter->trapFnc )
573 {
574 int trapped = IoAdapter->trapped;
575 IoAdapter->trapFnc (IoAdapter) ;
576 /*
577 Firs trap, also notify user if supported
578 */
579 if (!trapped && IoAdapter->trapped && IoAdapter->os_trap_nfy_Fnc) {
580 (*(IoAdapter->os_trap_nfy_Fnc))(IoAdapter, IoAdapter->ANum);
581 }
582 }
583}
584/*------------------------------------------------------------------*/
585/* ram access functions for memory mapped cards */
586/*------------------------------------------------------------------*/
587byte mem_in (ADAPTER *a, void *addr)
588{
589 byte val;
590 volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
591 val = READ_BYTE(Base + (unsigned long)addr);
592 DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
593 return (val);
594}
595word mem_inw (ADAPTER *a, void *addr)
596{
597 word val;
598 volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
599 val = READ_WORD((Base + (unsigned long)addr));
600 DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
601 return (val);
602}
603void mem_in_dw (ADAPTER *a, void *addr, dword* data, int dwords)
604{
605 volatile byte __iomem * Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
606 while (dwords--) {
607 *data++ = READ_DWORD((Base + (unsigned long)addr));
608 addr+=4;
609 }
610 DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
611}
612void mem_in_buffer (ADAPTER *a, void *addr, void *buffer, word length)
613{
614 volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
615 memcpy_fromio(buffer, (Base + (unsigned long)addr), length);
616 DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
617}
618void mem_look_ahead (ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
619{
620 PISDN_ADAPTER IoAdapter = (PISDN_ADAPTER)a->io ;
621 IoAdapter->RBuffer.length = mem_inw (a, &RBuffer->length) ;
622 mem_in_buffer (a, RBuffer->P, IoAdapter->RBuffer.P,
623 IoAdapter->RBuffer.length) ;
624 e->RBuffer = (DBUFFER *)&IoAdapter->RBuffer ;
625}
626void mem_out (ADAPTER *a, void *addr, byte data)
627{
628 volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
629 WRITE_BYTE(Base + (unsigned long)addr, data);
630 DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
631}
632void mem_outw (ADAPTER *a, void *addr, word data)
633{
634 volatile byte __iomem * Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
635 WRITE_WORD((Base + (unsigned long)addr), data);
636 DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
637}
638void mem_out_dw (ADAPTER *a, void *addr, const dword* data, int dwords)
639{
640 volatile byte __iomem * Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
641 while (dwords--) {
642 WRITE_DWORD((Base + (unsigned long)addr), *data);
643 addr+=4;
644 data++;
645 }
646 DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
647}
648void mem_out_buffer (ADAPTER *a, void *addr, void *buffer, word length)
649{
650 volatile byte __iomem * Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
651 memcpy_toio((Base + (unsigned long)addr), buffer, length) ;
652 DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
653}
654void mem_inc (ADAPTER *a, void *addr)
655{
656 volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io);
657 byte x = READ_BYTE(Base + (unsigned long)addr);
658 WRITE_BYTE(Base + (unsigned long)addr, x + 1);
659 DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base);
660}
661/*------------------------------------------------------------------*/
662/* ram access functions for io-mapped cards */
663/*------------------------------------------------------------------*/
664byte io_in(ADAPTER * a, void * adr)
665{
666 byte val;
667 byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
668 outppw(Port + 4, (word)(unsigned long)adr);
669 val = inpp(Port);
670 DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
671 return(val);
672}
673word io_inw(ADAPTER * a, void * adr)
674{
675 word val;
676 byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
677 outppw(Port + 4, (word)(unsigned long)adr);
678 val = inppw(Port);
679 DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
680 return(val);
681}
682void io_in_buffer(ADAPTER * a, void * adr, void * buffer, word len)
683{
684 byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
685 byte* P = (byte*)buffer;
686 if ((long)adr & 1) {
687 outppw(Port+4, (word)(unsigned long)adr);
688 *P = inpp(Port);
689 P++;
690 adr = ((byte *) adr) + 1;
691 len--;
692 if (!len) {
693 DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
694 return;
695 }
696 }
697 outppw(Port+4, (word)(unsigned long)adr);
698 inppw_buffer (Port, P, len+1);
699 DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
700}
701void io_look_ahead(ADAPTER * a, PBUFFER * RBuffer, ENTITY * e)
702{
703 byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
704 outppw(Port+4, (word)(unsigned long)RBuffer);
705 ((PISDN_ADAPTER)a->io)->RBuffer.length = inppw(Port);
706 inppw_buffer (Port, ((PISDN_ADAPTER)a->io)->RBuffer.P, ((PISDN_ADAPTER)a->io)->RBuffer.length + 1);
707 e->RBuffer = (DBUFFER *) &(((PISDN_ADAPTER)a->io)->RBuffer);
708 DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
709}
710void io_out(ADAPTER * a, void * adr, byte data)
711{
712 byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
713 outppw(Port+4, (word)(unsigned long)adr);
714 outpp(Port, data);
715 DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
716}
717void io_outw(ADAPTER * a, void * adr, word data)
718{
719 byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
720 outppw(Port+4, (word)(unsigned long)adr);
721 outppw(Port, data);
722 DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
723}
724void io_out_buffer(ADAPTER * a, void * adr, void * buffer, word len)
725{
726 byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
727 byte* P = (byte*)buffer;
728 if ((long)adr & 1) {
729 outppw(Port+4, (word)(unsigned long)adr);
730 outpp(Port, *P);
731 P++;
732 adr = ((byte *) adr) + 1;
733 len--;
734 if (!len) {
735 DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
736 return;
737 }
738 }
739 outppw(Port+4, (word)(unsigned long)adr);
740 outppw_buffer (Port, P, len+1);
741 DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
742}
743void io_inc(ADAPTER * a, void * adr)
744{
745 byte x;
746 byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
747 outppw(Port+4, (word)(unsigned long)adr);
748 x = inpp(Port);
749 outppw(Port+4, (word)(unsigned long)adr);
750 outpp(Port, x+1);
751 DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
752}
753/*------------------------------------------------------------------*/
754/* OS specific functions related to queuing of entities */
755/*------------------------------------------------------------------*/
756void free_entity(ADAPTER * a, byte e_no)
757{
758 PISDN_ADAPTER IoAdapter;
759 diva_os_spin_lock_magic_t irql;
760 IoAdapter = (PISDN_ADAPTER) a->io;
761 diva_os_enter_spin_lock (&IoAdapter->data_spin_lock, &irql, "data_free");
762 IoAdapter->e_tbl[e_no].e = NULL;
763 IoAdapter->e_count--;
764 diva_os_leave_spin_lock (&IoAdapter->data_spin_lock, &irql, "data_free");
765}
766void assign_queue(ADAPTER * a, byte e_no, word ref)
767{
768 PISDN_ADAPTER IoAdapter;
769 diva_os_spin_lock_magic_t irql;
770 IoAdapter = (PISDN_ADAPTER) a->io;
771 diva_os_enter_spin_lock (&IoAdapter->data_spin_lock, &irql, "data_assign");
772 IoAdapter->e_tbl[e_no].assign_ref = ref;
773 IoAdapter->e_tbl[e_no].next = (byte)IoAdapter->assign;
774 IoAdapter->assign = e_no;
775 diva_os_leave_spin_lock (&IoAdapter->data_spin_lock, &irql, "data_assign");
776}
777byte get_assign(ADAPTER * a, word ref)
778{
779 PISDN_ADAPTER IoAdapter;
780 diva_os_spin_lock_magic_t irql;
781 byte e_no;
782 IoAdapter = (PISDN_ADAPTER) a->io;
783 diva_os_enter_spin_lock (&IoAdapter->data_spin_lock,
784 &irql,
785 "data_assign_get");
786 for(e_no = (byte)IoAdapter->assign;
787 e_no && IoAdapter->e_tbl[e_no].assign_ref!=ref;
788 e_no = IoAdapter->e_tbl[e_no].next);
789 diva_os_leave_spin_lock (&IoAdapter->data_spin_lock,
790 &irql,
791 "data_assign_get");
792 return e_no;
793}
794void req_queue(ADAPTER * a, byte e_no)
795{
796 PISDN_ADAPTER IoAdapter;
797 diva_os_spin_lock_magic_t irql;
798 IoAdapter = (PISDN_ADAPTER) a->io;
799 diva_os_enter_spin_lock (&IoAdapter->data_spin_lock, &irql, "data_req_q");
800 IoAdapter->e_tbl[e_no].next = 0;
801 if(IoAdapter->head) {
802 IoAdapter->e_tbl[IoAdapter->tail].next = e_no;
803 IoAdapter->tail = e_no;
804 }
805 else {
806 IoAdapter->head = e_no;
807 IoAdapter->tail = e_no;
808 }
809 diva_os_leave_spin_lock (&IoAdapter->data_spin_lock, &irql, "data_req_q");
810}
811byte look_req(ADAPTER * a)
812{
813 PISDN_ADAPTER IoAdapter;
814 IoAdapter = (PISDN_ADAPTER) a->io;
815 return ((byte)IoAdapter->head) ;
816}
817void next_req(ADAPTER * a)
818{
819 PISDN_ADAPTER IoAdapter;
820 diva_os_spin_lock_magic_t irql;
821 IoAdapter = (PISDN_ADAPTER) a->io;
822 diva_os_enter_spin_lock (&IoAdapter->data_spin_lock, &irql, "data_req_next");
823 IoAdapter->head = IoAdapter->e_tbl[IoAdapter->head].next;
824 if(!IoAdapter->head) IoAdapter->tail = 0;
825 diva_os_leave_spin_lock (&IoAdapter->data_spin_lock, &irql, "data_req_next");
826}
827/*------------------------------------------------------------------*/
828/* memory map functions */
829/*------------------------------------------------------------------*/
830ENTITY * entity_ptr(ADAPTER * a, byte e_no)
831{
832 PISDN_ADAPTER IoAdapter;
833 IoAdapter = (PISDN_ADAPTER) a->io;
834 return (IoAdapter->e_tbl[e_no].e);
835}
836void * PTR_X(ADAPTER * a, ENTITY * e)
837{
838 return ((void *) e->X);
839}
840void * PTR_R(ADAPTER * a, ENTITY * e)
841{
842 return ((void *) e->R);
843}
844void * PTR_P(ADAPTER * a, ENTITY * e, void * P)
845{
846 return P;
847}
848void CALLBACK(ADAPTER * a, ENTITY * e)
849{
850 if ( e && e->callback )
851 e->callback (e) ;
852}
diff --git a/drivers/isdn/hardware/eicon/io.h b/drivers/isdn/hardware/eicon/io.h
new file mode 100644
index 000000000000..0c6c650d76bb
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/io.h
@@ -0,0 +1,308 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef __DIVA_XDI_COMMON_IO_H_INC__ /* { */
27#define __DIVA_XDI_COMMON_IO_H_INC__
28/*
29 maximum = 16 adapters
30 */
31#define DI_MAX_LINKS MAX_ADAPTER
32#define ISDN_MAX_NUM_LEN 60
33/* --------------------------------------------------------------------------
34 structure for quadro card management (obsolete for
35 systems that do provide per card load event)
36 -------------------------------------------------------------------------- */
37typedef struct {
38 dword Num ;
39 DEVICE_NAME DeviceName[4] ;
40 PISDN_ADAPTER QuadroAdapter[4] ;
41} ADAPTER_LIST_ENTRY, *PADAPTER_LIST_ENTRY ;
42/* --------------------------------------------------------------------------
43 Special OS memory support structures
44 -------------------------------------------------------------------------- */
45#define MAX_MAPPED_ENTRIES 8
46typedef struct {
47 void * Address;
48 dword Length;
49} ADAPTER_MEMORY ;
50/* --------------------------------------------------------------------------
51 Configuration of XDI clients carried by XDI
52 -------------------------------------------------------------------------- */
53#define DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON 0x01
54#define DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON 0x02
55typedef struct _diva_xdi_capi_cfg {
56 byte cfg_1;
57} diva_xdi_capi_cfg_t;
58/* --------------------------------------------------------------------------
59 Main data structure kept per adapter
60 -------------------------------------------------------------------------- */
61struct _ISDN_ADAPTER {
62 void (* DIRequest)(PISDN_ADAPTER, ENTITY *) ;
63 int State ; /* from NT4 1.srv, a good idea, but a poor achievment */
64 int Initialized ;
65 int RegisteredWithDidd ;
66 int Unavailable ; /* callback function possible? */
67 int ResourcesClaimed ;
68 int PnpBiosConfigUsed ;
69 dword Logging ;
70 dword features ;
71 char ProtocolIdString[80] ;
72 /*
73 remember mapped memory areas
74 */
75 ADAPTER_MEMORY MappedMemory[MAX_MAPPED_ENTRIES] ;
76 CARD_PROPERTIES Properties ;
77 dword cardType ;
78 dword protocol_id ; /* configured protocol identifier */
79 char protocol_name[8] ; /* readable name of protocol */
80 dword BusType ;
81 dword BusNumber ;
82 dword slotNumber ;
83 dword slotId ;
84 dword ControllerNumber ; /* for QUADRO cards only */
85 PISDN_ADAPTER MultiMaster ; /* for 4-BRI card only - use MultiMaster or QuadroList */
86 PADAPTER_LIST_ENTRY QuadroList ; /* for QUADRO card only */
87 PDEVICE_OBJECT DeviceObject ;
88 dword DeviceId ;
89 diva_os_adapter_irq_info_t irq_info;
90 dword volatile IrqCount ;
91 int trapped ;
92 dword DspCodeBaseAddr ;
93 dword MaxDspCodeSize ;
94 dword downloadAddr ;
95 dword DspCodeBaseAddrTable[4] ; /* add. for MultiMaster */
96 dword MaxDspCodeSizeTable[4] ; /* add. for MultiMaster */
97 dword downloadAddrTable[4] ; /* add. for MultiMaster */
98 dword MemoryBase ;
99 dword MemorySize ;
100 byte __iomem *Address ;
101 byte __iomem *Config ;
102 byte __iomem *Control ;
103 byte __iomem *reset ;
104 byte __iomem *port ;
105 byte __iomem *ram ;
106 byte __iomem *cfg ;
107 byte __iomem *prom ;
108 byte __iomem *ctlReg ;
109 struct pc_maint *pcm ;
110 diva_os_dependent_devica_name_t os_name;
111 byte Name[32] ;
112 dword serialNo ;
113 dword ANum ;
114 dword ArchiveType ; /* ARCHIVE_TYPE_NONE ..._SINGLE ..._USGEN ..._MULTI */
115 char *ProtocolSuffix ; /* internal protocolfile table */
116 char Archive[32] ;
117 char Protocol[32] ;
118 char AddDownload[32] ; /* Dsp- or other additional download files */
119 char Oad1[ISDN_MAX_NUM_LEN] ;
120 char Osa1[ISDN_MAX_NUM_LEN] ;
121 char Oad2[ISDN_MAX_NUM_LEN] ;
122 char Osa2[ISDN_MAX_NUM_LEN] ;
123 char Spid1[ISDN_MAX_NUM_LEN] ;
124 char Spid2[ISDN_MAX_NUM_LEN] ;
125 byte nosig ;
126 byte BriLayer2LinkCount ; /* amount of TEI's that adapter will support in P2MP mode */
127 dword Channels ;
128 dword tei ;
129 dword nt2 ;
130 dword TerminalCount ;
131 dword WatchDog ;
132 dword Permanent ;
133 dword BChMask ; /* B channel mask for unchannelized modes */
134 dword StableL2 ;
135 dword DidLen ;
136 dword NoOrderCheck ;
137 dword ForceLaw; /* VoiceCoding - default:0, a-law: 1, my-law: 2 */
138 dword SigFlags ;
139 dword LowChannel ;
140 dword NoHscx30 ;
141 dword ProtVersion ;
142 dword crc4 ;
143 dword L1TristateOrQsig ; /* enable Layer 1 Tristate (bit 2)Or Qsig params (bit 0,1)*/
144 dword InitialDspInfo ;
145 dword ModemGuardTone ;
146 dword ModemMinSpeed ;
147 dword ModemMaxSpeed ;
148 dword ModemOptions ;
149 dword ModemOptions2 ;
150 dword ModemNegotiationMode ;
151 dword ModemModulationsMask ;
152 dword ModemTransmitLevel ;
153 dword FaxOptions ;
154 dword FaxMaxSpeed ;
155 dword Part68LevelLimiter ;
156 dword UsEktsNumCallApp ;
157 byte UsEktsFeatAddConf ;
158 byte UsEktsFeatRemoveConf ;
159 byte UsEktsFeatCallTransfer ;
160 byte UsEktsFeatMsgWaiting ;
161 byte QsigDialect;
162 byte ForceVoiceMailAlert;
163 byte DisableAutoSpid;
164 byte ModemCarrierWaitTimeSec;
165 byte ModemCarrierLossWaitTimeTenthSec;
166 byte PiafsLinkTurnaroundInFrames;
167 byte DiscAfterProgress;
168 byte AniDniLimiter[3];
169 byte TxAttenuation; /* PRI/E1 only: attenuate TX signal */
170 word QsigFeatures;
171 dword GenerateRingtone ;
172 dword SupplementaryServicesFeatures;
173 dword R2Dialect;
174 dword R2CasOptions;
175 dword FaxV34Options;
176 dword DisabledDspMask;
177 dword AdapterTestMask;
178 dword DspImageLength;
179 word AlertToIn20mSecTicks;
180 word ModemEyeSetup;
181 byte R2CtryLength;
182 byte CCBSRelTimer;
183 byte *PcCfgBufferFile;/* flexible parameter via file */
184 byte *PcCfgBuffer ; /* flexible parameter via multistring */
185 diva_os_dump_file_t dump_file; /* dump memory to file at lowest irq level */
186 diva_os_board_trace_t board_trace ; /* traces from the board */
187 diva_os_spin_lock_t isr_spin_lock;
188 diva_os_spin_lock_t data_spin_lock;
189 diva_os_soft_isr_t req_soft_isr;
190 diva_os_soft_isr_t isr_soft_isr;
191 diva_os_atomic_t in_dpc;
192 PBUFFER RBuffer; /* Copy of receive lookahead buffer */
193 word e_max;
194 word e_count;
195 E_INFO *e_tbl;
196 word assign; /* list of pending ASSIGNs */
197 word head; /* head of request queue */
198 word tail; /* tail of request queue */
199 ADAPTER a ; /* not a separate structure */
200 void (* out)(ADAPTER * a) ;
201 byte (* dpc)(ADAPTER * a) ;
202 byte (* tst_irq)(ADAPTER * a) ;
203 void (* clr_irq)(ADAPTER * a) ;
204 int (* load)(PISDN_ADAPTER) ;
205 int (* mapmem)(PISDN_ADAPTER) ;
206 int (* chkIrq)(PISDN_ADAPTER) ;
207 void (* disIrq)(PISDN_ADAPTER) ;
208 void (* start)(PISDN_ADAPTER) ;
209 void (* stop)(PISDN_ADAPTER) ;
210 void (* rstFnc)(PISDN_ADAPTER) ;
211 void (* trapFnc)(PISDN_ADAPTER) ;
212 dword (* DetectDsps)(PISDN_ADAPTER) ;
213 void (* os_trap_nfy_Fnc)(PISDN_ADAPTER, dword) ;
214 diva_os_isr_callback_t diva_isr_handler;
215 dword sdram_bar; /* must be 32 bit */
216 dword fpga_features;
217 volatile int pcm_pending;
218 volatile void * pcm_data;
219 diva_xdi_capi_cfg_t capi_cfg;
220 dword tasks;
221 void *dma_map;
222 int (*DivaAdapterTestProc)(PISDN_ADAPTER);
223 void *AdapterTestMemoryStart;
224 dword AdapterTestMemoryLength;
225 const byte* cfg_lib_memory_init;
226 dword cfg_lib_memory_init_length;
227};
228/* ---------------------------------------------------------------------
229 Entity table
230 --------------------------------------------------------------------- */
231struct e_info_s {
232 ENTITY * e;
233 byte next; /* chaining index */
234 word assign_ref; /* assign reference */
235};
236/* ---------------------------------------------------------------------
237 S-cards shared ram structure for loading
238 --------------------------------------------------------------------- */
239struct s_load {
240 byte ctrl;
241 byte card;
242 byte msize;
243 byte fill0;
244 word ebit;
245 word elocl;
246 word eloch;
247 byte reserved[20];
248 word signature;
249 byte fill[224];
250 byte b[256];
251};
252#define PR_RAM ((struct pr_ram *)0)
253#define RAM ((struct dual *)0)
254/* ---------------------------------------------------------------------
255 platform specific conversions
256 --------------------------------------------------------------------- */
257extern void * PTR_P(ADAPTER * a, ENTITY * e, void * P);
258extern void * PTR_X(ADAPTER * a, ENTITY * e);
259extern void * PTR_R(ADAPTER * a, ENTITY * e);
260extern void CALLBACK(ADAPTER * a, ENTITY * e);
261extern void set_ram(void * * adr_ptr);
262/* ---------------------------------------------------------------------
263 ram access functions for io mapped cards
264 --------------------------------------------------------------------- */
265byte io_in(ADAPTER * a, void * adr);
266word io_inw(ADAPTER * a, void * adr);
267void io_in_buffer(ADAPTER * a, void * adr, void * P, word length);
268void io_look_ahead(ADAPTER * a, PBUFFER * RBuffer, ENTITY * e);
269void io_out(ADAPTER * a, void * adr, byte data);
270void io_outw(ADAPTER * a, void * adr, word data);
271void io_out_buffer(ADAPTER * a, void * adr, void * P, word length);
272void io_inc(ADAPTER * a, void * adr);
273void bri_in_buffer (PISDN_ADAPTER IoAdapter, dword Pos,
274 void *Buf, dword Len);
275int bri_out_buffer (PISDN_ADAPTER IoAdapter, dword Pos,
276 void *Buf, dword Len, int Verify);
277/* ---------------------------------------------------------------------
278 ram access functions for memory mapped cards
279 --------------------------------------------------------------------- */
280byte mem_in(ADAPTER * a, void * adr);
281word mem_inw(ADAPTER * a, void * adr);
282void mem_in_buffer(ADAPTER * a, void * adr, void * P, word length);
283void mem_look_ahead(ADAPTER * a, PBUFFER * RBuffer, ENTITY * e);
284void mem_out(ADAPTER * a, void * adr, byte data);
285void mem_outw(ADAPTER * a, void * adr, word data);
286void mem_out_buffer(ADAPTER * a, void * adr, void * P, word length);
287void mem_inc(ADAPTER * a, void * adr);
288void mem_in_dw (ADAPTER *a, void *addr, dword* data, int dwords);
289void mem_out_dw (ADAPTER *a, void *addr, const dword* data, int dwords);
290/* ---------------------------------------------------------------------
291 functions exported by io.c
292 --------------------------------------------------------------------- */
293extern IDI_CALL Requests[MAX_ADAPTER] ;
294extern void DIDpcRoutine (struct _diva_os_soft_isr* psoft_isr,
295 void* context);
296extern void request (PISDN_ADAPTER, ENTITY *) ;
297/* ---------------------------------------------------------------------
298 trapFn helpers, used to recover debug trace from dead card
299 --------------------------------------------------------------------- */
300typedef struct {
301 word *buf ;
302 word cnt ;
303 word out ;
304} Xdesc ;
305extern void dump_trap_frame (PISDN_ADAPTER IoAdapter, byte __iomem *exception) ;
306extern void dump_xlog_buffer (PISDN_ADAPTER IoAdapter, Xdesc *xlogDesc) ;
307/* --------------------------------------------------------------------- */
308#endif /* } __DIVA_XDI_COMMON_IO_H_INC__ */
diff --git a/drivers/isdn/hardware/eicon/istream.c b/drivers/isdn/hardware/eicon/istream.c
new file mode 100644
index 000000000000..23139668d9b1
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/istream.c
@@ -0,0 +1,226 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#include "platform.h"
27#if defined(DIVA_ISTREAM) /* { */
28#include "pc.h"
29#include "pr_pc.h"
30#include "di_defs.h"
31#include "divasync.h"
32#include "di.h"
33#if !defined USE_EXTENDED_DEBUGS
34 #include "dimaint.h"
35#else
36 #define dprintf
37#endif
38#include "dfifo.h"
39int diva_istream_write (void* context,
40 int Id,
41 void* data,
42 int length,
43 int final,
44 byte usr1,
45 byte usr2);
46int diva_istream_read (void* context,
47 int Id,
48 void* data,
49 int max_length,
50 int* final,
51 byte* usr1,
52 byte* usr2);
53/* -------------------------------------------------------------------
54 Does provide iStream interface to the client
55 ------------------------------------------------------------------- */
56void diva_xdi_provide_istream_info (ADAPTER* a,
57 diva_xdi_stream_interface_t* pi) {
58 pi->provided_service = 0;
59}
60/* ------------------------------------------------------------------
61 Does write the data from caller's buffer to the card's
62 stream interface.
63 If synchronous service was requested, then function
64 does return amount of data written to stream.
65 'final' does indicate that pice of data to be written is
66 final part of frame (necessary only by structured datatransfer)
67 return 0 if zero lengh packet was written
68 return -1 if stream is full
69 ------------------------------------------------------------------ */
70int diva_istream_write (void* context,
71 int Id,
72 void* data,
73 int length,
74 int final,
75 byte usr1,
76 byte usr2) {
77 ADAPTER* a = (ADAPTER*)context;
78 int written = 0, to_write = -1;
79 char tmp[4];
80 byte* data_ptr = (byte*)data;
81 for (;;) {
82 a->ram_in_dw (a,
83#ifdef PLATFORM_GT_32BIT
84 ULongToPtr(a->tx_stream[Id] + a->tx_pos[Id]),
85#else
86 (void*)(a->tx_stream[Id] + a->tx_pos[Id]),
87#endif
88 (dword*)&tmp[0],
89 1);
90 if (tmp[0] & DIVA_DFIFO_READY) { /* No free blocks more */
91 if (to_write < 0)
92 return (-1); /* was not able to write */
93 break; /* only part of message was written */
94 }
95 to_write = MIN(length, DIVA_DFIFO_DATA_SZ);
96 if (to_write) {
97 a->ram_out_buffer (a,
98#ifdef PLATFORM_GT_32BIT
99 ULongToPtr(a->tx_stream[Id] + a->tx_pos[Id]+4),
100#else
101 (void*)(a->tx_stream[Id] + a->tx_pos[Id] + 4),
102#endif
103 data_ptr,
104 (word)to_write);
105 length -= to_write;
106 written += to_write;
107 data_ptr += to_write;
108 }
109 tmp[1] = (char)to_write;
110 tmp[0] = (tmp[0] & DIVA_DFIFO_WRAP) |
111 DIVA_DFIFO_READY |
112 ((!length && final) ? DIVA_DFIFO_LAST : 0);
113 if (tmp[0] & DIVA_DFIFO_LAST) {
114 tmp[2] = usr1;
115 tmp[3] = usr2;
116 }
117 a->ram_out_dw (a,
118#ifdef PLATFORM_GT_32BIT
119 ULongToPtr(a->tx_stream[Id] + a->tx_pos[Id]),
120#else
121 (void*)(a->tx_stream[Id] + a->tx_pos[Id]),
122#endif
123 (dword*)&tmp[0],
124 1);
125 if (tmp[0] & DIVA_DFIFO_WRAP) {
126 a->tx_pos[Id] = 0;
127 } else {
128 a->tx_pos[Id] += DIVA_DFIFO_STEP;
129 }
130 if (!length) {
131 break;
132 }
133 }
134 return (written);
135}
136/* -------------------------------------------------------------------
137 In case of SYNCRONOUS service:
138 Does write data from stream in caller's buffer.
139 Does return amount of data written to buffer
140 Final flag is set on return if last part of structured frame
141 was received
142 return 0 if zero packet was received
143 return -1 if stream is empty
144 return -2 if read buffer does not profide sufficient space
145 to accommodate entire segment
146 max_length should be at least 68 bytes
147 ------------------------------------------------------------------- */
148int diva_istream_read (void* context,
149 int Id,
150 void* data,
151 int max_length,
152 int* final,
153 byte* usr1,
154 byte* usr2) {
155 ADAPTER* a = (ADAPTER*)context;
156 int read = 0, to_read = -1;
157 char tmp[4];
158 byte* data_ptr = (byte*)data;
159 *final = 0;
160 for (;;) {
161 a->ram_in_dw (a,
162#ifdef PLATFORM_GT_32BIT
163 ULongToPtr(a->rx_stream[Id] + a->rx_pos[Id]),
164#else
165 (void*)(a->rx_stream[Id] + a->rx_pos[Id]),
166#endif
167 (dword*)&tmp[0],
168 1);
169 if (tmp[1] > max_length) {
170 if (to_read < 0)
171 return (-2); /* was not able to read */
172 break;
173 }
174 if (!(tmp[0] & DIVA_DFIFO_READY)) {
175 if (to_read < 0)
176 return (-1); /* was not able to read */
177 break;
178 }
179 to_read = MIN(max_length, tmp[1]);
180 if (to_read) {
181 a->ram_in_buffer(a,
182#ifdef PLATFORM_GT_32BIT
183 ULongToPtr(a->rx_stream[Id] + a->rx_pos[Id] + 4),
184#else
185 (void*)(a->rx_stream[Id] + a->rx_pos[Id] + 4),
186#endif
187 data_ptr,
188 (word)to_read);
189 max_length -= to_read;
190 read += to_read;
191 data_ptr += to_read;
192 }
193 if (tmp[0] & DIVA_DFIFO_LAST) {
194 *final = 1;
195 }
196 tmp[0] &= DIVA_DFIFO_WRAP;
197 a->ram_out_dw(a,
198#ifdef PLATFORM_GT_32BIT
199 ULongToPtr(a->rx_stream[Id] + a->rx_pos[Id]),
200#else
201 (void*)(a->rx_stream[Id] + a->rx_pos[Id]),
202#endif
203 (dword*)&tmp[0],
204 1);
205 if (tmp[0] & DIVA_DFIFO_WRAP) {
206 a->rx_pos[Id] = 0;
207 } else {
208 a->rx_pos[Id] += DIVA_DFIFO_STEP;
209 }
210 if (*final) {
211 if (usr1)
212 *usr1 = tmp[2];
213 if (usr2)
214 *usr2 = tmp[3];
215 break;
216 }
217 }
218 return (read);
219}
220/* ---------------------------------------------------------------------
221 Does check if one of streams had caused interrupt and does
222 wake up corresponding application
223 --------------------------------------------------------------------- */
224void pr_stream (ADAPTER * a) {
225}
226#endif /* } */
diff --git a/drivers/isdn/hardware/eicon/kst_ifc.h b/drivers/isdn/hardware/eicon/kst_ifc.h
new file mode 100644
index 000000000000..203189a010c2
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/kst_ifc.h
@@ -0,0 +1,336 @@
1/*
2 *
3 Copyright (c) Eicon Networks, 2000.
4 *
5 This source file is supplied for the use with
6 Eicon Networks range of DIVA Server Adapters.
7 *
8 Eicon File Revision : 1.9
9 *
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14 *
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License for more details.
19 *
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25#ifndef __DIVA_EICON_TRACE_API__
26#define __DIVA_EICON_TRACE_API__
27
28#define DIVA_TRACE_LINE_TYPE_LEN 64
29#define DIVA_TRACE_IE_LEN 64
30#define DIVA_TRACE_FAX_PRMS_LEN 128
31
32typedef struct _diva_trace_ie {
33 byte length;
34 byte data[DIVA_TRACE_IE_LEN];
35} diva_trace_ie_t;
36
37/*
38 Structure used to represent "State\\BX\\Modem" directory
39 to user.
40 */
41typedef struct _diva_trace_modem_state {
42 dword ChannelNumber;
43
44 dword Event;
45
46 dword Norm;
47
48 dword Options; /* Options received from Application */
49
50 dword TxSpeed;
51 dword RxSpeed;
52
53 dword RoundtripMsec;
54
55 dword SymbolRate;
56
57 int RxLeveldBm;
58 int EchoLeveldBm;
59
60 dword SNRdb;
61 dword MAE;
62
63 dword LocalRetrains;
64 dword RemoteRetrains;
65 dword LocalResyncs;
66 dword RemoteResyncs;
67
68 dword DiscReason;
69
70} diva_trace_modem_state_t;
71
72/*
73 Representation of "State\\BX\\FAX" directory
74 */
75typedef struct _diva_trace_fax_state {
76 dword ChannelNumber;
77 dword Event;
78 dword Page_Counter;
79 dword Features;
80 char Station_ID[DIVA_TRACE_FAX_PRMS_LEN];
81 char Subaddress[DIVA_TRACE_FAX_PRMS_LEN];
82 char Password[DIVA_TRACE_FAX_PRMS_LEN];
83 dword Speed;
84 dword Resolution;
85 dword Paper_Width;
86 dword Paper_Length;
87 dword Scanline_Time;
88 dword Disc_Reason;
89 dword dummy;
90} diva_trace_fax_state_t;
91
92/*
93 Structure used to represent Interface State in the abstract
94 and interface/D-channel protocol independent form.
95 */
96typedef struct _diva_trace_interface_state {
97 char Layer1[DIVA_TRACE_LINE_TYPE_LEN];
98 char Layer2[DIVA_TRACE_LINE_TYPE_LEN];
99} diva_trace_interface_state_t;
100
101typedef struct _diva_incoming_call_statistics {
102 dword Calls;
103 dword Connected;
104 dword User_Busy;
105 dword Call_Rejected;
106 dword Wrong_Number;
107 dword Incompatible_Dst;
108 dword Out_of_Order;
109 dword Ignored;
110} diva_incoming_call_statistics_t;
111
112typedef struct _diva_outgoing_call_statistics {
113 dword Calls;
114 dword Connected;
115 dword User_Busy;
116 dword No_Answer;
117 dword Wrong_Number;
118 dword Call_Rejected;
119 dword Other_Failures;
120} diva_outgoing_call_statistics_t;
121
122typedef struct _diva_modem_call_statistics {
123 dword Disc_Normal;
124 dword Disc_Unspecified;
125 dword Disc_Busy_Tone;
126 dword Disc_Congestion;
127 dword Disc_Carr_Wait;
128 dword Disc_Trn_Timeout;
129 dword Disc_Incompat;
130 dword Disc_Frame_Rej;
131 dword Disc_V42bis;
132} diva_modem_call_statistics_t;
133
134typedef struct _diva_fax_call_statistics {
135 dword Disc_Normal;
136 dword Disc_Not_Ident;
137 dword Disc_No_Response;
138 dword Disc_Retries;
139 dword Disc_Unexp_Msg;
140 dword Disc_No_Polling;
141 dword Disc_Training;
142 dword Disc_Unexpected;
143 dword Disc_Application;
144 dword Disc_Incompat;
145 dword Disc_No_Command;
146 dword Disc_Long_Msg;
147 dword Disc_Supervisor;
148 dword Disc_SUB_SEP_PWD;
149 dword Disc_Invalid_Msg;
150 dword Disc_Page_Coding;
151 dword Disc_App_Timeout;
152 dword Disc_Unspecified;
153} diva_fax_call_statistics_t;
154
155typedef struct _diva_prot_statistics {
156 dword X_Frames;
157 dword X_Bytes;
158 dword X_Errors;
159 dword R_Frames;
160 dword R_Bytes;
161 dword R_Errors;
162} diva_prot_statistics_t;
163
164typedef struct _diva_ifc_statistics {
165 diva_incoming_call_statistics_t inc;
166 diva_outgoing_call_statistics_t outg;
167 diva_modem_call_statistics_t mdm;
168 diva_fax_call_statistics_t fax;
169 diva_prot_statistics_t b1;
170 diva_prot_statistics_t b2;
171 diva_prot_statistics_t d1;
172 diva_prot_statistics_t d2;
173} diva_ifc_statistics_t;
174
175/*
176 Structure used to represent "State\\BX" directory
177 to user.
178 */
179typedef struct _diva_trace_line_state {
180 dword ChannelNumber;
181
182 char Line[DIVA_TRACE_LINE_TYPE_LEN];
183
184 char Framing[DIVA_TRACE_LINE_TYPE_LEN];
185
186 char Layer2[DIVA_TRACE_LINE_TYPE_LEN];
187 char Layer3[DIVA_TRACE_LINE_TYPE_LEN];
188
189 char RemoteAddress[DIVA_TRACE_LINE_TYPE_LEN];
190 char RemoteSubAddress[DIVA_TRACE_LINE_TYPE_LEN];
191
192 char LocalAddress[DIVA_TRACE_LINE_TYPE_LEN];
193 char LocalSubAddress[DIVA_TRACE_LINE_TYPE_LEN];
194
195 diva_trace_ie_t call_BC;
196 diva_trace_ie_t call_HLC;
197 diva_trace_ie_t call_LLC;
198
199 dword Charges;
200
201 dword CallReference;
202
203 dword LastDisconnecCause;
204
205 char UserID[DIVA_TRACE_LINE_TYPE_LEN];
206
207 diva_trace_modem_state_t modem;
208 diva_trace_fax_state_t fax;
209
210 diva_trace_interface_state_t* pInterface;
211
212 diva_ifc_statistics_t* pInterfaceStat;
213
214} diva_trace_line_state_t;
215
216#define DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE ('l')
217#define DIVA_SUPER_TRACE_NOTIFY_MODEM_CHANGE ('m')
218#define DIVA_SUPER_TRACE_NOTIFY_FAX_CHANGE ('f')
219#define DIVA_SUPER_TRACE_INTERFACE_CHANGE ('i')
220#define DIVA_SUPER_TRACE_NOTIFY_STAT_CHANGE ('s')
221#define DIVA_SUPER_TRACE_NOTIFY_MDM_STAT_CHANGE ('M')
222#define DIVA_SUPER_TRACE_NOTIFY_FAX_STAT_CHANGE ('F')
223
224struct _diva_strace_library_interface;
225typedef void (*diva_trace_channel_state_change_proc_t)(void* user_context,
226 struct _diva_strace_library_interface* hLib,
227 int Adapter,
228 diva_trace_line_state_t* channel, int notify_subject);
229typedef void (*diva_trace_channel_trace_proc_t)(void* user_context,
230 struct _diva_strace_library_interface* hLib,
231 int Adapter, void* xlog_buffer, int length);
232typedef void (*diva_trace_error_proc_t)(void* user_context,
233 struct _diva_strace_library_interface* hLib,
234 int Adapter,
235 int error, const char* file, int line);
236
237/*
238 This structure creates interface from user to library
239 */
240typedef struct _diva_trace_library_user_interface {
241 void* user_context;
242 diva_trace_channel_state_change_proc_t notify_proc;
243 diva_trace_channel_trace_proc_t trace_proc;
244 diva_trace_error_proc_t error_notify_proc;
245} diva_trace_library_user_interface_t;
246
247/*
248 Interface from Library to User
249 */
250typedef int (*DivaSTraceLibraryStart_proc_t)(void* hLib);
251typedef int (*DivaSTraceLibraryFinit_proc_t)(void* hLib);
252typedef int (*DivaSTraceMessageInput_proc_t)(void* hLib);
253typedef void* (*DivaSTraceGetHandle_proc_t)(void* hLib);
254
255/*
256 Turn Audio Tap trace on/off
257 Channel should be in the range 1 ... Number of Channels
258 */
259typedef int (*DivaSTraceSetAudioTap_proc_t)(void* hLib, int Channel, int on);
260
261/*
262 Turn B-channel trace on/off
263 Channel should be in the range 1 ... Number of Channels
264 */
265typedef int (*DivaSTraceSetBChannel_proc_t)(void* hLib, int Channel, int on);
266
267/*
268 Turn D-channel (Layer1/Layer2/Layer3) trace on/off
269 Layer1 - All D-channel frames received/sent over the interface
270 inclusive Layer 2 headers, Layer 2 frames and TEI management frames
271 Layer2 - Events from LAPD protocol instance with SAPI of signalling protocol
272 Layer3 - All D-channel frames addressed to assigned to the card TEI and
273 SAPI of signalling protocol, and signalling protocol events.
274 */
275typedef int (*DivaSTraceSetDChannel_proc_t)(void* hLib, int on);
276
277/*
278 Get overall card statistics
279 */
280typedef int (*DivaSTraceGetOutgoingCallStatistics_proc_t)(void* hLib);
281typedef int (*DivaSTraceGetIncomingCallStatistics_proc_t)(void* hLib);
282typedef int (*DivaSTraceGetModemStatistics_proc_t)(void* hLib);
283typedef int (*DivaSTraceGetFaxStatistics_proc_t)(void* hLib);
284typedef int (*DivaSTraceGetBLayer1Statistics_proc_t)(void* hLib);
285typedef int (*DivaSTraceGetBLayer2Statistics_proc_t)(void* hLib);
286typedef int (*DivaSTraceGetDLayer1Statistics_proc_t)(void* hLib);
287typedef int (*DivaSTraceGetDLayer2Statistics_proc_t)(void* hLib);
288
289/*
290 Call control
291 */
292typedef int (*DivaSTraceClearCall_proc_t)(void* hLib, int Channel);
293
294typedef struct _diva_strace_library_interface {
295 void* hLib;
296 DivaSTraceLibraryStart_proc_t DivaSTraceLibraryStart;
297 DivaSTraceLibraryStart_proc_t DivaSTraceLibraryStop;
298 DivaSTraceLibraryFinit_proc_t DivaSTraceLibraryFinit;
299 DivaSTraceMessageInput_proc_t DivaSTraceMessageInput;
300 DivaSTraceGetHandle_proc_t DivaSTraceGetHandle;
301 DivaSTraceSetAudioTap_proc_t DivaSTraceSetAudioTap;
302 DivaSTraceSetBChannel_proc_t DivaSTraceSetBChannel;
303 DivaSTraceSetDChannel_proc_t DivaSTraceSetDChannel;
304 DivaSTraceSetDChannel_proc_t DivaSTraceSetInfo;
305 DivaSTraceGetOutgoingCallStatistics_proc_t \
306 DivaSTraceGetOutgoingCallStatistics;
307 DivaSTraceGetIncomingCallStatistics_proc_t \
308 DivaSTraceGetIncomingCallStatistics;
309 DivaSTraceGetModemStatistics_proc_t \
310 DivaSTraceGetModemStatistics;
311 DivaSTraceGetFaxStatistics_proc_t \
312 DivaSTraceGetFaxStatistics;
313 DivaSTraceGetBLayer1Statistics_proc_t \
314 DivaSTraceGetBLayer1Statistics;
315 DivaSTraceGetBLayer2Statistics_proc_t \
316 DivaSTraceGetBLayer2Statistics;
317 DivaSTraceGetDLayer1Statistics_proc_t \
318 DivaSTraceGetDLayer1Statistics;
319 DivaSTraceGetDLayer2Statistics_proc_t \
320 DivaSTraceGetDLayer2Statistics;
321 DivaSTraceClearCall_proc_t DivaSTraceClearCall;
322} diva_strace_library_interface_t;
323
324/*
325 Create and return Library interface
326 */
327diva_strace_library_interface_t* DivaSTraceLibraryCreateInstance (int Adapter,
328 const diva_trace_library_user_interface_t* user_proc,
329 byte* pmem);
330dword DivaSTraceGetMemotyRequirement (int channels);
331
332#define DIVA_MAX_ADAPTERS 64
333#define DIVA_MAX_LINES 32
334
335#endif
336
diff --git a/drivers/isdn/hardware/eicon/main_if.h b/drivers/isdn/hardware/eicon/main_if.h
new file mode 100644
index 000000000000..0ea339afd424
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/main_if.h
@@ -0,0 +1,50 @@
1/*
2 *
3 Copyright (c) Eicon Technology Corporation, 2000.
4 *
5 This source file is supplied for the use with Eicon
6 Technology Corporation's range of DIVA Server Adapters.
7 *
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12 *
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
15 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 See the GNU General Public License for more details.
17 *
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 */
23/*------------------------------------------------------------------*/
24/* file: main_if.h */
25/*------------------------------------------------------------------*/
26# ifndef MAIN_IF___H
27# define MAIN_IF___H
28
29# include "debug_if.h"
30
31void DI_lock (void) ;
32void DI_unlock (void) ;
33
34#ifdef NOT_YET_NEEDED
35void DI_nttime (LARGE_INTEGER *NTtime) ;
36void DI_ntlcltime(LARGE_INTEGER *NTtime, LARGE_INTEGER *lclNTtime) ;
37void DI_nttimefields(LARGE_INTEGER *NTtime, TIME_FIELDS *TimeFields);
38unsigned long DI_wintime(LARGE_INTEGER *NTtime) ;
39
40unsigned short DiInsertProcessorNumber (int type) ;
41void DiProcessEventLog (unsigned short id, unsigned long msgID, va_list ap);
42
43void StartIoctlTimer (void (*Handler)(void), unsigned long msec) ;
44void StopIoctlTimer (void) ;
45void UnpendIoctl (DbgRequest *pDbgReq) ;
46#endif
47
48void add_to_q(int, char* , unsigned int);
49# endif /* MAIN_IF___H */
50
diff --git a/drivers/isdn/hardware/eicon/maintidi.c b/drivers/isdn/hardware/eicon/maintidi.c
new file mode 100644
index 000000000000..23960cb6eaab
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/maintidi.c
@@ -0,0 +1,2194 @@
1/*
2 *
3 Copyright (c) Eicon Networks, 2000.
4 *
5 This source file is supplied for the use with
6 Eicon Networks range of DIVA Server Adapters.
7 *
8 Eicon File Revision : 1.9
9 *
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14 *
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License for more details.
19 *
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25#include "platform.h"
26#include "kst_ifc.h"
27#include "di_defs.h"
28#include "maintidi.h"
29#include "pc.h"
30#include "man_defs.h"
31
32
33extern void diva_mnt_internal_dprintf (dword drv_id, dword type, char* p, ...);
34
35#define MODEM_PARSE_ENTRIES 16 /* amount of variables of interest */
36#define FAX_PARSE_ENTRIES 12 /* amount of variables of interest */
37#define LINE_PARSE_ENTRIES 15 /* amount of variables of interest */
38#define STAT_PARSE_ENTRIES 70 /* amount of variables of interest */
39
40/*
41 LOCAL FUNCTIONS
42 */
43static int DivaSTraceLibraryStart (void* hLib);
44static int DivaSTraceLibraryStop (void* hLib);
45static int SuperTraceLibraryFinit (void* hLib);
46static void* SuperTraceGetHandle (void* hLib);
47static int SuperTraceMessageInput (void* hLib);
48static int SuperTraceSetAudioTap (void* hLib, int Channel, int on);
49static int SuperTraceSetBChannel (void* hLib, int Channel, int on);
50static int SuperTraceSetDChannel (void* hLib, int on);
51static int SuperTraceSetInfo (void* hLib, int on);
52static int SuperTraceClearCall (void* hLib, int Channel);
53static int SuperTraceGetOutgoingCallStatistics (void* hLib);
54static int SuperTraceGetIncomingCallStatistics (void* hLib);
55static int SuperTraceGetModemStatistics (void* hLib);
56static int SuperTraceGetFaxStatistics (void* hLib);
57static int SuperTraceGetBLayer1Statistics (void* hLib);
58static int SuperTraceGetBLayer2Statistics (void* hLib);
59static int SuperTraceGetDLayer1Statistics (void* hLib);
60static int SuperTraceGetDLayer2Statistics (void* hLib);
61
62/*
63 LOCAL FUNCTIONS
64 */
65static int ScheduleNextTraceRequest (diva_strace_context_t* pLib);
66static int process_idi_event (diva_strace_context_t* pLib,
67 diva_man_var_header_t* pVar);
68static int process_idi_info (diva_strace_context_t* pLib,
69 diva_man_var_header_t* pVar);
70static int diva_modem_event (diva_strace_context_t* pLib, int Channel);
71static int diva_fax_event (diva_strace_context_t* pLib, int Channel);
72static int diva_line_event (diva_strace_context_t* pLib, int Channel);
73static int diva_modem_info (diva_strace_context_t* pLib,
74 int Channel,
75 diva_man_var_header_t* pVar);
76static int diva_fax_info (diva_strace_context_t* pLib,
77 int Channel,
78 diva_man_var_header_t* pVar);
79static int diva_line_info (diva_strace_context_t* pLib,
80 int Channel,
81 diva_man_var_header_t* pVar);
82static int diva_ifc_statistics (diva_strace_context_t* pLib,
83 diva_man_var_header_t* pVar);
84static diva_man_var_header_t* get_next_var (diva_man_var_header_t* pVar);
85static diva_man_var_header_t* find_var (diva_man_var_header_t* pVar,
86 const char* name);
87static int diva_strace_read_int (diva_man_var_header_t* pVar, int* var);
88static int diva_strace_read_uint (diva_man_var_header_t* pVar, dword* var);
89static int diva_strace_read_asz (diva_man_var_header_t* pVar, char* var);
90static int diva_strace_read_asc (diva_man_var_header_t* pVar, char* var);
91static int diva_strace_read_ie (diva_man_var_header_t* pVar,
92 diva_trace_ie_t* var);
93static void diva_create_parse_table (diva_strace_context_t* pLib);
94static void diva_trace_error (diva_strace_context_t* pLib,
95 int error, const char* file, int line);
96static void diva_trace_notify_user (diva_strace_context_t* pLib,
97 int Channel,
98 int notify_subject);
99static int diva_trace_read_variable (diva_man_var_header_t* pVar,
100 void* variable);
101
102/*
103 Initialize the library and return context
104 of the created trace object that will represent
105 the IDI adapter.
106 Return 0 on error.
107 */
108diva_strace_library_interface_t* DivaSTraceLibraryCreateInstance (int Adapter,
109 const diva_trace_library_user_interface_t* user_proc,
110 byte* pmem) {
111 diva_strace_context_t* pLib = (diva_strace_context_t*)pmem;
112 int i;
113
114 if (!pLib) {
115 return NULL;
116 }
117
118 pmem += sizeof(*pLib);
119 memset(pLib, 0x00, sizeof(*pLib));
120
121 pLib->Adapter = Adapter;
122
123 /*
124 Set up Library Interface
125 */
126 pLib->instance.hLib = pLib;
127 pLib->instance.DivaSTraceLibraryStart = DivaSTraceLibraryStart;
128 pLib->instance.DivaSTraceLibraryStop = DivaSTraceLibraryStop;
129 pLib->instance.DivaSTraceLibraryFinit = SuperTraceLibraryFinit;
130 pLib->instance.DivaSTraceMessageInput = SuperTraceMessageInput;
131 pLib->instance.DivaSTraceGetHandle = SuperTraceGetHandle;
132 pLib->instance.DivaSTraceSetAudioTap = SuperTraceSetAudioTap;
133 pLib->instance.DivaSTraceSetBChannel = SuperTraceSetBChannel;
134 pLib->instance.DivaSTraceSetDChannel = SuperTraceSetDChannel;
135 pLib->instance.DivaSTraceSetInfo = SuperTraceSetInfo;
136 pLib->instance.DivaSTraceGetOutgoingCallStatistics = \
137 SuperTraceGetOutgoingCallStatistics;
138 pLib->instance.DivaSTraceGetIncomingCallStatistics = \
139 SuperTraceGetIncomingCallStatistics;
140 pLib->instance.DivaSTraceGetModemStatistics = \
141 SuperTraceGetModemStatistics;
142 pLib->instance.DivaSTraceGetFaxStatistics = \
143 SuperTraceGetFaxStatistics;
144 pLib->instance.DivaSTraceGetBLayer1Statistics = \
145 SuperTraceGetBLayer1Statistics;
146 pLib->instance.DivaSTraceGetBLayer2Statistics = \
147 SuperTraceGetBLayer2Statistics;
148 pLib->instance.DivaSTraceGetDLayer1Statistics = \
149 SuperTraceGetDLayer1Statistics;
150 pLib->instance.DivaSTraceGetDLayer2Statistics = \
151 SuperTraceGetDLayer2Statistics;
152 pLib->instance.DivaSTraceClearCall = SuperTraceClearCall;
153
154
155 if (user_proc) {
156 pLib->user_proc_table.user_context = user_proc->user_context;
157 pLib->user_proc_table.notify_proc = user_proc->notify_proc;
158 pLib->user_proc_table.trace_proc = user_proc->trace_proc;
159 pLib->user_proc_table.error_notify_proc = user_proc->error_notify_proc;
160 }
161
162 if (!(pLib->hAdapter = SuperTraceOpenAdapter (Adapter))) {
163 diva_mnt_internal_dprintf (0, DLI_ERR, "Can not open XDI adapter");
164 return NULL;
165 }
166 pLib->Channels = SuperTraceGetNumberOfChannels (pLib->hAdapter);
167
168 /*
169 Calculate amount of parte table entites necessary to translate
170 information from all events of onterest
171 */
172 pLib->parse_entries = (MODEM_PARSE_ENTRIES + FAX_PARSE_ENTRIES + \
173 STAT_PARSE_ENTRIES + \
174 LINE_PARSE_ENTRIES + 1) * pLib->Channels;
175 pLib->parse_table = (diva_strace_path2action_t*)pmem;
176
177 for (i = 0; i < 30; i++) {
178 pLib->lines[i].pInterface = &pLib->Interface;
179 pLib->lines[i].pInterfaceStat = &pLib->InterfaceStat;
180 }
181
182 pLib->e.R = &pLib->RData;
183
184 pLib->req_busy = 1;
185 pLib->rc_ok = ASSIGN_OK;
186
187 diva_create_parse_table (pLib);
188
189 return ((diva_strace_library_interface_t*)pLib);
190}
191
192static int DivaSTraceLibraryStart (void* hLib) {
193 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
194
195 return (SuperTraceASSIGN (pLib->hAdapter, pLib->buffer));
196}
197
198/*
199 Return (-1) on error
200 Return (0) if was initiated or pending
201 Return (1) if removal is complete
202 */
203static int DivaSTraceLibraryStop (void* hLib) {
204 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
205
206 if (!pLib->e.Id) { /* Was never started/assigned */
207 return (1);
208 }
209
210 switch (pLib->removal_state) {
211 case 0:
212 pLib->removal_state = 1;
213 ScheduleNextTraceRequest(pLib);
214 break;
215
216 case 3:
217 return (1);
218 }
219
220 return (0);
221}
222
223static int SuperTraceLibraryFinit (void* hLib) {
224 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
225 if (pLib) {
226 if (pLib->hAdapter) {
227 SuperTraceCloseAdapter (pLib->hAdapter);
228 }
229 return (0);
230 }
231 return (-1);
232}
233
234static void* SuperTraceGetHandle (void* hLib) {
235 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
236
237 return (&pLib->e);
238}
239
240/*
241 After library handle object is gone in signaled state
242 this function should be called and will pick up incoming
243 IDI messages (return codes and indications).
244 */
245static int SuperTraceMessageInput (void* hLib) {
246 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
247 int ret = 0;
248 byte Rc, Ind;
249
250 if (pLib->e.complete == 255) {
251 /*
252 Process return code
253 */
254 pLib->req_busy = 0;
255 Rc = pLib->e.Rc;
256 pLib->e.Rc = 0;
257
258 if (pLib->removal_state == 2) {
259 pLib->removal_state = 3;
260 return (0);
261 }
262
263 if (Rc != pLib->rc_ok) {
264 int ignore = 0;
265 /*
266 Auto-detect amount of events/channels and features
267 */
268 if (pLib->general_b_ch_event == 1) {
269 pLib->general_b_ch_event = 2;
270 ignore = 1;
271 } else if (pLib->general_fax_event == 1) {
272 pLib->general_fax_event = 2;
273 ignore = 1;
274 } else if (pLib->general_mdm_event == 1) {
275 pLib->general_mdm_event = 2;
276 ignore = 1;
277 } else if ((pLib->ChannelsTraceActive < pLib->Channels) && pLib->ChannelsTraceActive) {
278 pLib->ChannelsTraceActive = pLib->Channels;
279 ignore = 1;
280 } else if (pLib->ModemTraceActive < pLib->Channels) {
281 pLib->ModemTraceActive = pLib->Channels;
282 ignore = 1;
283 } else if (pLib->FaxTraceActive < pLib->Channels) {
284 pLib->FaxTraceActive = pLib->Channels;
285 ignore = 1;
286 } else if (pLib->audio_trace_init == 2) {
287 ignore = 1;
288 pLib->audio_trace_init = 1;
289 } else if (pLib->eye_pattern_pending) {
290 pLib->eye_pattern_pending = 0;
291 ignore = 1;
292 } else if (pLib->audio_tap_pending) {
293 pLib->audio_tap_pending = 0;
294 ignore = 1;
295 }
296
297 if (!ignore) {
298 return (-1); /* request failed */
299 }
300 } else {
301 if (pLib->general_b_ch_event == 1) {
302 pLib->ChannelsTraceActive = pLib->Channels;
303 pLib->general_b_ch_event = 2;
304 } else if (pLib->general_fax_event == 1) {
305 pLib->general_fax_event = 2;
306 pLib->FaxTraceActive = pLib->Channels;
307 } else if (pLib->general_mdm_event == 1) {
308 pLib->general_mdm_event = 2;
309 pLib->ModemTraceActive = pLib->Channels;
310 }
311 }
312 if (pLib->audio_trace_init == 2) {
313 pLib->audio_trace_init = 1;
314 }
315 pLib->rc_ok = 0xff; /* default OK after assign was done */
316 if ((ret = ScheduleNextTraceRequest(pLib))) {
317 return (-1);
318 }
319 } else {
320 /*
321 Process indication
322 Always 'RNR' indication if return code is pending
323 */
324 Ind = pLib->e.Ind;
325 pLib->e.Ind = 0;
326 if (pLib->removal_state) {
327 pLib->e.RNum = 0;
328 pLib->e.RNR = 2;
329 } else if (pLib->req_busy) {
330 pLib->e.RNum = 0;
331 pLib->e.RNR = 1;
332 } else {
333 if (pLib->e.complete != 0x02) {
334 /*
335 Look-ahead call, set up buffers
336 */
337 pLib->e.RNum = 1;
338 pLib->e.R->P = (byte*)&pLib->buffer[0];
339 pLib->e.R->PLength = (word)(sizeof(pLib->buffer) - 1);
340
341 } else {
342 /*
343 Indication reception complete, process it now
344 */
345 byte* p = (byte*)&pLib->buffer[0];
346 pLib->buffer[pLib->e.R->PLength] = 0; /* terminate I.E. with zero */
347
348 switch (Ind) {
349 case MAN_COMBI_IND: {
350 int total_length = pLib->e.R->PLength;
351 word this_ind_length;
352
353 while (total_length > 3 && *p) {
354 Ind = *p++;
355 this_ind_length = (word)p[0] | ((word)p[1] << 8);
356 p += 2;
357
358 switch (Ind) {
359 case MAN_INFO_IND:
360 if (process_idi_info (pLib, (diva_man_var_header_t*)p)) {
361 return (-1);
362 }
363 break;
364 case MAN_EVENT_IND:
365 if (process_idi_event (pLib, (diva_man_var_header_t*)p)) {
366 return (-1);
367 }
368 break;
369 case MAN_TRACE_IND:
370 if (pLib->trace_on == 1) {
371 /*
372 Ignore first trace event that is result of
373 EVENT_ON operation
374 */
375 pLib->trace_on++;
376 } else {
377 /*
378 Delivery XLOG buffer to application
379 */
380 if (pLib->user_proc_table.trace_proc) {
381 (*(pLib->user_proc_table.trace_proc))(pLib->user_proc_table.user_context,
382 &pLib->instance, pLib->Adapter,
383 p, this_ind_length);
384 }
385 }
386 break;
387 default:
388 diva_mnt_internal_dprintf (0, DLI_ERR, "Unknon IDI Ind (DMA mode): %02x", Ind);
389 }
390 p += (this_ind_length+1);
391 total_length -= (4 + this_ind_length);
392 }
393 } break;
394 case MAN_INFO_IND:
395 if (process_idi_info (pLib, (diva_man_var_header_t*)p)) {
396 return (-1);
397 }
398 break;
399 case MAN_EVENT_IND:
400 if (process_idi_event (pLib, (diva_man_var_header_t*)p)) {
401 return (-1);
402 }
403 break;
404 case MAN_TRACE_IND:
405 if (pLib->trace_on == 1) {
406 /*
407 Ignore first trace event that is result of
408 EVENT_ON operation
409 */
410 pLib->trace_on++;
411 } else {
412 /*
413 Delivery XLOG buffer to application
414 */
415 if (pLib->user_proc_table.trace_proc) {
416 (*(pLib->user_proc_table.trace_proc))(pLib->user_proc_table.user_context,
417 &pLib->instance, pLib->Adapter,
418 p, pLib->e.R->PLength);
419 }
420 }
421 break;
422 default:
423 diva_mnt_internal_dprintf (0, DLI_ERR, "Unknon IDI Ind: %02x", Ind);
424 }
425 }
426 }
427 }
428
429 if ((ret = ScheduleNextTraceRequest(pLib))) {
430 return (-1);
431 }
432
433 return (ret);
434}
435
436/*
437 Internal state machine responsible for scheduling of requests
438 */
439static int ScheduleNextTraceRequest (diva_strace_context_t* pLib) {
440 char name[64];
441 int ret = 0;
442 int i;
443
444 if (pLib->req_busy) {
445 return (0);
446 }
447
448 if (pLib->removal_state == 1) {
449 if (SuperTraceREMOVE (pLib->hAdapter)) {
450 pLib->removal_state = 3;
451 } else {
452 pLib->req_busy = 1;
453 pLib->removal_state = 2;
454 }
455 return (0);
456 }
457
458 if (pLib->removal_state) {
459 return (0);
460 }
461
462 if (!pLib->general_b_ch_event) {
463 if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, "State\\B Event", pLib->buffer))) {
464 return (-1);
465 }
466 pLib->general_b_ch_event = 1;
467 pLib->req_busy = 1;
468 return (0);
469 }
470
471 if (!pLib->general_fax_event) {
472 if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, "State\\FAX Event", pLib->buffer))) {
473 return (-1);
474 }
475 pLib->general_fax_event = 1;
476 pLib->req_busy = 1;
477 return (0);
478 }
479
480 if (!pLib->general_mdm_event) {
481 if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, "State\\Modem Event", pLib->buffer))) {
482 return (-1);
483 }
484 pLib->general_mdm_event = 1;
485 pLib->req_busy = 1;
486 return (0);
487 }
488
489 if (pLib->ChannelsTraceActive < pLib->Channels) {
490 pLib->ChannelsTraceActive++;
491 sprintf (name, "State\\B%d\\Line", pLib->ChannelsTraceActive);
492 if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
493 pLib->ChannelsTraceActive--;
494 return (-1);
495 }
496 pLib->req_busy = 1;
497 return (0);
498 }
499
500 if (pLib->ModemTraceActive < pLib->Channels) {
501 pLib->ModemTraceActive++;
502 sprintf (name, "State\\B%d\\Modem\\Event", pLib->ModemTraceActive);
503 if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
504 pLib->ModemTraceActive--;
505 return (-1);
506 }
507 pLib->req_busy = 1;
508 return (0);
509 }
510
511 if (pLib->FaxTraceActive < pLib->Channels) {
512 pLib->FaxTraceActive++;
513 sprintf (name, "State\\B%d\\FAX\\Event", pLib->FaxTraceActive);
514 if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
515 pLib->FaxTraceActive--;
516 return (-1);
517 }
518 pLib->req_busy = 1;
519 return (0);
520 }
521
522 if (!pLib->trace_mask_init) {
523 word tmp = 0x0000;
524 if (SuperTraceWriteVar (pLib->hAdapter,
525 pLib->buffer,
526 "Trace\\Event Enable",
527 &tmp,
528 0x87, /* MI_BITFLD */
529 sizeof(tmp))) {
530 return (-1);
531 }
532 pLib->trace_mask_init = 1;
533 pLib->req_busy = 1;
534 return (0);
535 }
536
537 if (!pLib->audio_trace_init) {
538 dword tmp = 0x00000000;
539 if (SuperTraceWriteVar (pLib->hAdapter,
540 pLib->buffer,
541 "Trace\\AudioCh# Enable",
542 &tmp,
543 0x87, /* MI_BITFLD */
544 sizeof(tmp))) {
545 return (-1);
546 }
547 pLib->audio_trace_init = 2;
548 pLib->req_busy = 1;
549 return (0);
550 }
551
552 if (!pLib->bchannel_init) {
553 dword tmp = 0x00000000;
554 if (SuperTraceWriteVar (pLib->hAdapter,
555 pLib->buffer,
556 "Trace\\B-Ch# Enable",
557 &tmp,
558 0x87, /* MI_BITFLD */
559 sizeof(tmp))) {
560 return (-1);
561 }
562 pLib->bchannel_init = 1;
563 pLib->req_busy = 1;
564 return (0);
565 }
566
567 if (!pLib->trace_length_init) {
568 word tmp = 30;
569 if (SuperTraceWriteVar (pLib->hAdapter,
570 pLib->buffer,
571 "Trace\\Max Log Length",
572 &tmp,
573 0x82, /* MI_UINT */
574 sizeof(tmp))) {
575 return (-1);
576 }
577 pLib->trace_length_init = 1;
578 pLib->req_busy = 1;
579 return (0);
580 }
581
582 if (!pLib->trace_on) {
583 if (SuperTraceTraceOnRequest (pLib->hAdapter,
584 "Trace\\Log Buffer",
585 pLib->buffer)) {
586 return (-1);
587 }
588 pLib->trace_on = 1;
589 pLib->req_busy = 1;
590 return (0);
591 }
592
593 if (pLib->trace_event_mask != pLib->current_trace_event_mask) {
594 if (SuperTraceWriteVar (pLib->hAdapter,
595 pLib->buffer,
596 "Trace\\Event Enable",
597 &pLib->trace_event_mask,
598 0x87, /* MI_BITFLD */
599 sizeof(pLib->trace_event_mask))) {
600 return (-1);
601 }
602 pLib->current_trace_event_mask = pLib->trace_event_mask;
603 pLib->req_busy = 1;
604 return (0);
605 }
606
607 if ((pLib->audio_tap_pending >= 0) && (pLib->audio_tap_mask != pLib->current_audio_tap_mask)) {
608 if (SuperTraceWriteVar (pLib->hAdapter,
609 pLib->buffer,
610 "Trace\\AudioCh# Enable",
611 &pLib->audio_tap_mask,
612 0x87, /* MI_BITFLD */
613 sizeof(pLib->audio_tap_mask))) {
614 return (-1);
615 }
616 pLib->current_audio_tap_mask = pLib->audio_tap_mask;
617 pLib->audio_tap_pending = 1;
618 pLib->req_busy = 1;
619 return (0);
620 }
621
622 if ((pLib->eye_pattern_pending >= 0) && (pLib->audio_tap_mask != pLib->current_eye_pattern_mask)) {
623 if (SuperTraceWriteVar (pLib->hAdapter,
624 pLib->buffer,
625 "Trace\\EyeCh# Enable",
626 &pLib->audio_tap_mask,
627 0x87, /* MI_BITFLD */
628 sizeof(pLib->audio_tap_mask))) {
629 return (-1);
630 }
631 pLib->current_eye_pattern_mask = pLib->audio_tap_mask;
632 pLib->eye_pattern_pending = 1;
633 pLib->req_busy = 1;
634 return (0);
635 }
636
637 if (pLib->bchannel_trace_mask != pLib->current_bchannel_trace_mask) {
638 if (SuperTraceWriteVar (pLib->hAdapter,
639 pLib->buffer,
640 "Trace\\B-Ch# Enable",
641 &pLib->bchannel_trace_mask,
642 0x87, /* MI_BITFLD */
643 sizeof(pLib->bchannel_trace_mask))) {
644 return (-1);
645 }
646 pLib->current_bchannel_trace_mask = pLib->bchannel_trace_mask;
647 pLib->req_busy = 1;
648 return (0);
649 }
650
651 if (!pLib->trace_events_down) {
652 if (SuperTraceTraceOnRequest (pLib->hAdapter,
653 "Events Down",
654 pLib->buffer)) {
655 return (-1);
656 }
657 pLib->trace_events_down = 1;
658 pLib->req_busy = 1;
659 return (0);
660 }
661
662 if (!pLib->l1_trace) {
663 if (SuperTraceTraceOnRequest (pLib->hAdapter,
664 "State\\Layer1",
665 pLib->buffer)) {
666 return (-1);
667 }
668 pLib->l1_trace = 1;
669 pLib->req_busy = 1;
670 return (0);
671 }
672
673 if (!pLib->l2_trace) {
674 if (SuperTraceTraceOnRequest (pLib->hAdapter,
675 "State\\Layer2 No1",
676 pLib->buffer)) {
677 return (-1);
678 }
679 pLib->l2_trace = 1;
680 pLib->req_busy = 1;
681 return (0);
682 }
683
684 for (i = 0; i < 30; i++) {
685 if (pLib->pending_line_status & (1L << i)) {
686 sprintf (name, "State\\B%d", i+1);
687 if (SuperTraceReadRequest (pLib->hAdapter, name, pLib->buffer)) {
688 return (-1);
689 }
690 pLib->pending_line_status &= ~(1L << i);
691 pLib->req_busy = 1;
692 return (0);
693 }
694 if (pLib->pending_modem_status & (1L << i)) {
695 sprintf (name, "State\\B%d\\Modem", i+1);
696 if (SuperTraceReadRequest (pLib->hAdapter, name, pLib->buffer)) {
697 return (-1);
698 }
699 pLib->pending_modem_status &= ~(1L << i);
700 pLib->req_busy = 1;
701 return (0);
702 }
703 if (pLib->pending_fax_status & (1L << i)) {
704 sprintf (name, "State\\B%d\\FAX", i+1);
705 if (SuperTraceReadRequest (pLib->hAdapter, name, pLib->buffer)) {
706 return (-1);
707 }
708 pLib->pending_fax_status &= ~(1L << i);
709 pLib->req_busy = 1;
710 return (0);
711 }
712 if (pLib->clear_call_command & (1L << i)) {
713 sprintf (name, "State\\B%d\\Clear Call", i+1);
714 if (SuperTraceExecuteRequest (pLib->hAdapter, name, pLib->buffer)) {
715 return (-1);
716 }
717 pLib->clear_call_command &= ~(1L << i);
718 pLib->req_busy = 1;
719 return (0);
720 }
721 }
722
723 if (pLib->outgoing_ifc_stats) {
724 if (SuperTraceReadRequest (pLib->hAdapter,
725 "Statistics\\Outgoing Calls",
726 pLib->buffer)) {
727 return (-1);
728 }
729 pLib->outgoing_ifc_stats = 0;
730 pLib->req_busy = 1;
731 return (0);
732 }
733
734 if (pLib->incoming_ifc_stats) {
735 if (SuperTraceReadRequest (pLib->hAdapter,
736 "Statistics\\Incoming Calls",
737 pLib->buffer)) {
738 return (-1);
739 }
740 pLib->incoming_ifc_stats = 0;
741 pLib->req_busy = 1;
742 return (0);
743 }
744
745 if (pLib->modem_ifc_stats) {
746 if (SuperTraceReadRequest (pLib->hAdapter,
747 "Statistics\\Modem",
748 pLib->buffer)) {
749 return (-1);
750 }
751 pLib->modem_ifc_stats = 0;
752 pLib->req_busy = 1;
753 return (0);
754 }
755
756 if (pLib->fax_ifc_stats) {
757 if (SuperTraceReadRequest (pLib->hAdapter,
758 "Statistics\\FAX",
759 pLib->buffer)) {
760 return (-1);
761 }
762 pLib->fax_ifc_stats = 0;
763 pLib->req_busy = 1;
764 return (0);
765 }
766
767 if (pLib->b1_ifc_stats) {
768 if (SuperTraceReadRequest (pLib->hAdapter,
769 "Statistics\\B-Layer1",
770 pLib->buffer)) {
771 return (-1);
772 }
773 pLib->b1_ifc_stats = 0;
774 pLib->req_busy = 1;
775 return (0);
776 }
777
778 if (pLib->b2_ifc_stats) {
779 if (SuperTraceReadRequest (pLib->hAdapter,
780 "Statistics\\B-Layer2",
781 pLib->buffer)) {
782 return (-1);
783 }
784 pLib->b2_ifc_stats = 0;
785 pLib->req_busy = 1;
786 return (0);
787 }
788
789 if (pLib->d1_ifc_stats) {
790 if (SuperTraceReadRequest (pLib->hAdapter,
791 "Statistics\\D-Layer1",
792 pLib->buffer)) {
793 return (-1);
794 }
795 pLib->d1_ifc_stats = 0;
796 pLib->req_busy = 1;
797 return (0);
798 }
799
800 if (pLib->d2_ifc_stats) {
801 if (SuperTraceReadRequest (pLib->hAdapter,
802 "Statistics\\D-Layer2",
803 pLib->buffer)) {
804 return (-1);
805 }
806 pLib->d2_ifc_stats = 0;
807 pLib->req_busy = 1;
808 return (0);
809 }
810
811 if (!pLib->IncomingCallsCallsActive) {
812 pLib->IncomingCallsCallsActive = 1;
813 sprintf (name, "%s", "Statistics\\Incoming Calls\\Calls");
814 if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
815 pLib->IncomingCallsCallsActive = 0;
816 return (-1);
817 }
818 pLib->req_busy = 1;
819 return (0);
820 }
821 if (!pLib->IncomingCallsConnectedActive) {
822 pLib->IncomingCallsConnectedActive = 1;
823 sprintf (name, "%s", "Statistics\\Incoming Calls\\Connected");
824 if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
825 pLib->IncomingCallsConnectedActive = 0;
826 return (-1);
827 }
828 pLib->req_busy = 1;
829 return (0);
830 }
831 if (!pLib->OutgoingCallsCallsActive) {
832 pLib->OutgoingCallsCallsActive = 1;
833 sprintf (name, "%s", "Statistics\\Outgoing Calls\\Calls");
834 if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
835 pLib->OutgoingCallsCallsActive = 0;
836 return (-1);
837 }
838 pLib->req_busy = 1;
839 return (0);
840 }
841 if (!pLib->OutgoingCallsConnectedActive) {
842 pLib->OutgoingCallsConnectedActive = 1;
843 sprintf (name, "%s", "Statistics\\Outgoing Calls\\Connected");
844 if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
845 pLib->OutgoingCallsConnectedActive = 0;
846 return (-1);
847 }
848 pLib->req_busy = 1;
849 return (0);
850 }
851
852 return (0);
853}
854
855static int process_idi_event (diva_strace_context_t* pLib,
856 diva_man_var_header_t* pVar) {
857 const char* path = (char*)&pVar->path_length+1;
858 char name[64];
859 int i;
860
861 if (!strncmp("State\\B Event", path, pVar->path_length)) {
862 dword ch_id;
863 if (!diva_trace_read_variable (pVar, &ch_id)) {
864 if (!pLib->line_init_event && !pLib->pending_line_status) {
865 for (i = 1; i <= pLib->Channels; i++) {
866 diva_line_event(pLib, i);
867 }
868 return (0);
869 } else if (ch_id && ch_id <= pLib->Channels) {
870 return (diva_line_event(pLib, (int)ch_id));
871 }
872 return (0);
873 }
874 return (-1);
875 }
876
877 if (!strncmp("State\\FAX Event", path, pVar->path_length)) {
878 dword ch_id;
879 if (!diva_trace_read_variable (pVar, &ch_id)) {
880 if (!pLib->pending_fax_status && !pLib->fax_init_event) {
881 for (i = 1; i <= pLib->Channels; i++) {
882 diva_fax_event(pLib, i);
883 }
884 return (0);
885 } else if (ch_id && ch_id <= pLib->Channels) {
886 return (diva_fax_event(pLib, (int)ch_id));
887 }
888 return (0);
889 }
890 return (-1);
891 }
892
893 if (!strncmp("State\\Modem Event", path, pVar->path_length)) {
894 dword ch_id;
895 if (!diva_trace_read_variable (pVar, &ch_id)) {
896 if (!pLib->pending_modem_status && !pLib->modem_init_event) {
897 for (i = 1; i <= pLib->Channels; i++) {
898 diva_modem_event(pLib, i);
899 }
900 return (0);
901 } else if (ch_id && ch_id <= pLib->Channels) {
902 return (diva_modem_event(pLib, (int)ch_id));
903 }
904 return (0);
905 }
906 return (-1);
907 }
908
909 /*
910 First look for Line Event
911 */
912 for (i = 1; i <= pLib->Channels; i++) {
913 sprintf (name, "State\\B%d\\Line", i);
914 if (find_var (pVar, name)) {
915 return (diva_line_event(pLib, i));
916 }
917 }
918
919 /*
920 Look for Moden Progress Event
921 */
922 for (i = 1; i <= pLib->Channels; i++) {
923 sprintf (name, "State\\B%d\\Modem\\Event", i);
924 if (find_var (pVar, name)) {
925 return (diva_modem_event (pLib, i));
926 }
927 }
928
929 /*
930 Look for Fax Event
931 */
932 for (i = 1; i <= pLib->Channels; i++) {
933 sprintf (name, "State\\B%d\\FAX\\Event", i);
934 if (find_var (pVar, name)) {
935 return (diva_fax_event (pLib, i));
936 }
937 }
938
939 /*
940 Notification about loss of events
941 */
942 if (!strncmp("Events Down", path, pVar->path_length)) {
943 if (pLib->trace_events_down == 1) {
944 pLib->trace_events_down = 2;
945 } else {
946 diva_trace_error (pLib, 1, "Events Down", 0);
947 }
948 return (0);
949 }
950
951 if (!strncmp("State\\Layer1", path, pVar->path_length)) {
952 diva_strace_read_asz (pVar, &pLib->lines[0].pInterface->Layer1[0]);
953 if (pLib->l1_trace == 1) {
954 pLib->l1_trace = 2;
955 } else {
956 diva_trace_notify_user (pLib, 0, DIVA_SUPER_TRACE_INTERFACE_CHANGE);
957 }
958 return (0);
959 }
960 if (!strncmp("State\\Layer2 No1", path, pVar->path_length)) {
961 char* tmp = &pLib->lines[0].pInterface->Layer2[0];
962 dword l2_state;
963 diva_strace_read_uint (pVar, &l2_state);
964
965 switch (l2_state) {
966 case 0:
967 strcpy (tmp, "Idle");
968 break;
969 case 1:
970 strcpy (tmp, "Layer2 UP");
971 break;
972 case 2:
973 strcpy (tmp, "Layer2 Disconnecting");
974 break;
975 case 3:
976 strcpy (tmp, "Layer2 Connecting");
977 break;
978 case 4:
979 strcpy (tmp, "SPID Initializing");
980 break;
981 case 5:
982 strcpy (tmp, "SPID Initialised");
983 break;
984 case 6:
985 strcpy (tmp, "Layer2 Connecting");
986 break;
987
988 case 7:
989 strcpy (tmp, "Auto SPID Stopped");
990 break;
991
992 case 8:
993 strcpy (tmp, "Auto SPID Idle");
994 break;
995
996 case 9:
997 strcpy (tmp, "Auto SPID Requested");
998 break;
999
1000 case 10:
1001 strcpy (tmp, "Auto SPID Delivery");
1002 break;
1003
1004 case 11:
1005 strcpy (tmp, "Auto SPID Complete");
1006 break;
1007
1008 default:
1009 sprintf (tmp, "U:%d", (int)l2_state);
1010 }
1011 if (pLib->l2_trace == 1) {
1012 pLib->l2_trace = 2;
1013 } else {
1014 diva_trace_notify_user (pLib, 0, DIVA_SUPER_TRACE_INTERFACE_CHANGE);
1015 }
1016 return (0);
1017 }
1018
1019 if (!strncmp("Statistics\\Incoming Calls\\Calls", path, pVar->path_length) ||
1020 !strncmp("Statistics\\Incoming Calls\\Connected", path, pVar->path_length)) {
1021 return (SuperTraceGetIncomingCallStatistics (pLib));
1022 }
1023
1024 if (!strncmp("Statistics\\Outgoing Calls\\Calls", path, pVar->path_length) ||
1025 !strncmp("Statistics\\Outgoing Calls\\Connected", path, pVar->path_length)) {
1026 return (SuperTraceGetOutgoingCallStatistics (pLib));
1027 }
1028
1029 return (-1);
1030}
1031
1032static int diva_line_event (diva_strace_context_t* pLib, int Channel) {
1033 pLib->pending_line_status |= (1L << (Channel-1));
1034 return (0);
1035}
1036
1037static int diva_modem_event (diva_strace_context_t* pLib, int Channel) {
1038 pLib->pending_modem_status |= (1L << (Channel-1));
1039 return (0);
1040}
1041
1042static int diva_fax_event (diva_strace_context_t* pLib, int Channel) {
1043 pLib->pending_fax_status |= (1L << (Channel-1));
1044 return (0);
1045}
1046
1047/*
1048 Process INFO indications that arrive from the card
1049 Uses path of first I.E. to detect the source of the
1050 infication
1051 */
1052static int process_idi_info (diva_strace_context_t* pLib,
1053 diva_man_var_header_t* pVar) {
1054 const char* path = (char*)&pVar->path_length+1;
1055 char name[64];
1056 int i, len;
1057
1058 /*
1059 First look for Modem Status Info
1060 */
1061 for (i = pLib->Channels; i > 0; i--) {
1062 len = sprintf (name, "State\\B%d\\Modem", i);
1063 if (!strncmp(name, path, len)) {
1064 return (diva_modem_info (pLib, i, pVar));
1065 }
1066 }
1067
1068 /*
1069 Look for Fax Status Info
1070 */
1071 for (i = pLib->Channels; i > 0; i--) {
1072 len = sprintf (name, "State\\B%d\\FAX", i);
1073 if (!strncmp(name, path, len)) {
1074 return (diva_fax_info (pLib, i, pVar));
1075 }
1076 }
1077
1078 /*
1079 Look for Line Status Info
1080 */
1081 for (i = pLib->Channels; i > 0; i--) {
1082 len = sprintf (name, "State\\B%d", i);
1083 if (!strncmp(name, path, len)) {
1084 return (diva_line_info (pLib, i, pVar));
1085 }
1086 }
1087
1088 if (!diva_ifc_statistics (pLib, pVar)) {
1089 return (0);
1090 }
1091
1092 return (-1);
1093}
1094
1095/*
1096 MODEM INSTANCE STATE UPDATE
1097
1098 Update Modem Status Information and issue notification to user,
1099 that will inform about change in the state of modem instance, that is
1100 associuated with this channel
1101 */
1102static int diva_modem_info (diva_strace_context_t* pLib,
1103 int Channel,
1104 diva_man_var_header_t* pVar) {
1105 diva_man_var_header_t* cur;
1106 int i, nr = Channel - 1;
1107
1108 for (i = pLib->modem_parse_entry_first[nr];
1109 i <= pLib->modem_parse_entry_last[nr]; i++) {
1110 if ((cur = find_var (pVar, pLib->parse_table[i].path))) {
1111 if (diva_trace_read_variable (cur, pLib->parse_table[i].variable)) {
1112 diva_trace_error (pLib, -3 , __FILE__, __LINE__);
1113 return (-1);
1114 }
1115 } else {
1116 diva_trace_error (pLib, -2 , __FILE__, __LINE__);
1117 return (-1);
1118 }
1119 }
1120
1121 /*
1122 We do not use first event to notify user - this is the event that is
1123 generated as result of EVENT ON operation and is used only to initialize
1124 internal variables of application
1125 */
1126 if (pLib->modem_init_event & (1L << nr)) {
1127 diva_trace_notify_user (pLib, nr, DIVA_SUPER_TRACE_NOTIFY_MODEM_CHANGE);
1128 } else {
1129 pLib->modem_init_event |= (1L << nr);
1130 }
1131
1132 return (0);
1133}
1134
1135static int diva_fax_info (diva_strace_context_t* pLib,
1136 int Channel,
1137 diva_man_var_header_t* pVar) {
1138 diva_man_var_header_t* cur;
1139 int i, nr = Channel - 1;
1140
1141 for (i = pLib->fax_parse_entry_first[nr];
1142 i <= pLib->fax_parse_entry_last[nr]; i++) {
1143 if ((cur = find_var (pVar, pLib->parse_table[i].path))) {
1144 if (diva_trace_read_variable (cur, pLib->parse_table[i].variable)) {
1145 diva_trace_error (pLib, -3 , __FILE__, __LINE__);
1146 return (-1);
1147 }
1148 } else {
1149 diva_trace_error (pLib, -2 , __FILE__, __LINE__);
1150 return (-1);
1151 }
1152 }
1153
1154 /*
1155 We do not use first event to notify user - this is the event that is
1156 generated as result of EVENT ON operation and is used only to initialize
1157 internal variables of application
1158 */
1159 if (pLib->fax_init_event & (1L << nr)) {
1160 diva_trace_notify_user (pLib, nr, DIVA_SUPER_TRACE_NOTIFY_FAX_CHANGE);
1161 } else {
1162 pLib->fax_init_event |= (1L << nr);
1163 }
1164
1165 return (0);
1166}
1167
1168/*
1169 LINE STATE UPDATE
1170 Update Line Status Information and issue notification to user,
1171 that will inform about change in the line state.
1172 */
1173static int diva_line_info (diva_strace_context_t* pLib,
1174 int Channel,
1175 diva_man_var_header_t* pVar) {
1176 diva_man_var_header_t* cur;
1177 int i, nr = Channel - 1;
1178
1179 for (i = pLib->line_parse_entry_first[nr];
1180 i <= pLib->line_parse_entry_last[nr]; i++) {
1181 if ((cur = find_var (pVar, pLib->parse_table[i].path))) {
1182 if (diva_trace_read_variable (cur, pLib->parse_table[i].variable)) {
1183 diva_trace_error (pLib, -3 , __FILE__, __LINE__);
1184 return (-1);
1185 }
1186 } else {
1187 diva_trace_error (pLib, -2 , __FILE__, __LINE__);
1188 return (-1);
1189 }
1190 }
1191
1192 /*
1193 We do not use first event to notify user - this is the event that is
1194 generated as result of EVENT ON operation and is used only to initialize
1195 internal variables of application
1196
1197 Exception is is if the line is "online". In this case we have to notify
1198 user about this confition.
1199 */
1200 if (pLib->line_init_event & (1L << nr)) {
1201 diva_trace_notify_user (pLib, nr, DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE);
1202 } else {
1203 pLib->line_init_event |= (1L << nr);
1204 if (strcmp (&pLib->lines[nr].Line[0], "Idle")) {
1205 diva_trace_notify_user (pLib, nr, DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE);
1206 }
1207 }
1208
1209 return (0);
1210}
1211
1212/*
1213 Move position to next vatianle in the chain
1214 */
1215static diva_man_var_header_t* get_next_var (diva_man_var_header_t* pVar) {
1216 byte* msg = (byte*)pVar;
1217 byte* start;
1218 int msg_length;
1219
1220 if (*msg != ESC) return NULL;
1221
1222 start = msg + 2;
1223 msg_length = *(msg+1);
1224 msg = (start+msg_length);
1225
1226 if (*msg != ESC) return NULL;
1227
1228 return ((diva_man_var_header_t*)msg);
1229}
1230
1231/*
1232 Move position to variable with given name
1233 */
1234static diva_man_var_header_t* find_var (diva_man_var_header_t* pVar,
1235 const char* name) {
1236 const char* path;
1237
1238 do {
1239 path = (char*)&pVar->path_length+1;
1240
1241 if (!strncmp (name, path, pVar->path_length)) {
1242 break;
1243 }
1244 } while ((pVar = get_next_var (pVar)));
1245
1246 return (pVar);
1247}
1248
1249static void diva_create_line_parse_table (diva_strace_context_t* pLib,
1250 int Channel) {
1251 diva_trace_line_state_t* pLine = &pLib->lines[Channel];
1252 int nr = Channel+1;
1253
1254 if ((pLib->cur_parse_entry + LINE_PARSE_ENTRIES) >= pLib->parse_entries) {
1255 diva_trace_error (pLib, -1, __FILE__, __LINE__);
1256 return;
1257 }
1258
1259 pLine->ChannelNumber = nr;
1260
1261 pLib->line_parse_entry_first[Channel] = pLib->cur_parse_entry;
1262
1263 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1264 "State\\B%d\\Framing", nr);
1265 pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Framing[0];
1266
1267 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1268 "State\\B%d\\Line", nr);
1269 pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Line[0];
1270
1271 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1272 "State\\B%d\\Layer2", nr);
1273 pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Layer2[0];
1274
1275 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1276 "State\\B%d\\Layer3", nr);
1277 pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Layer3[0];
1278
1279 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1280 "State\\B%d\\Remote Address", nr);
1281 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1282 &pLine->RemoteAddress[0];
1283
1284 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1285 "State\\B%d\\Remote SubAddr", nr);
1286 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1287 &pLine->RemoteSubAddress[0];
1288
1289 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1290 "State\\B%d\\Local Address", nr);
1291 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1292 &pLine->LocalAddress[0];
1293
1294 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1295 "State\\B%d\\Local SubAddr", nr);
1296 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1297 &pLine->LocalSubAddress[0];
1298
1299 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1300 "State\\B%d\\BC", nr);
1301 pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->call_BC;
1302
1303 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1304 "State\\B%d\\HLC", nr);
1305 pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->call_HLC;
1306
1307 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1308 "State\\B%d\\LLC", nr);
1309 pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->call_LLC;
1310
1311 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1312 "State\\B%d\\Charges", nr);
1313 pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Charges;
1314
1315 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1316 "State\\B%d\\Call Reference", nr);
1317 pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->CallReference;
1318
1319 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1320 "State\\B%d\\Last Disc Cause", nr);
1321 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1322 &pLine->LastDisconnecCause;
1323
1324 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1325 "State\\B%d\\User ID", nr);
1326 pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->UserID[0];
1327
1328 pLib->line_parse_entry_last[Channel] = pLib->cur_parse_entry - 1;
1329}
1330
1331static void diva_create_fax_parse_table (diva_strace_context_t* pLib,
1332 int Channel) {
1333 diva_trace_fax_state_t* pFax = &pLib->lines[Channel].fax;
1334 int nr = Channel+1;
1335
1336 if ((pLib->cur_parse_entry + FAX_PARSE_ENTRIES) >= pLib->parse_entries) {
1337 diva_trace_error (pLib, -1, __FILE__, __LINE__);
1338 return;
1339 }
1340 pFax->ChannelNumber = nr;
1341
1342 pLib->fax_parse_entry_first[Channel] = pLib->cur_parse_entry;
1343
1344 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1345 "State\\B%d\\FAX\\Event", nr);
1346 pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Event;
1347
1348 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1349 "State\\B%d\\FAX\\Page Counter", nr);
1350 pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Page_Counter;
1351
1352 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1353 "State\\B%d\\FAX\\Features", nr);
1354 pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Features;
1355
1356 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1357 "State\\B%d\\FAX\\Station ID", nr);
1358 pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Station_ID[0];
1359
1360 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1361 "State\\B%d\\FAX\\Subaddress", nr);
1362 pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Subaddress[0];
1363
1364 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1365 "State\\B%d\\FAX\\Password", nr);
1366 pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Password[0];
1367
1368 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1369 "State\\B%d\\FAX\\Speed", nr);
1370 pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Speed;
1371
1372 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1373 "State\\B%d\\FAX\\Resolution", nr);
1374 pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Resolution;
1375
1376 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1377 "State\\B%d\\FAX\\Paper Width", nr);
1378 pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Paper_Width;
1379
1380 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1381 "State\\B%d\\FAX\\Paper Length", nr);
1382 pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Paper_Length;
1383
1384 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1385 "State\\B%d\\FAX\\Scanline Time", nr);
1386 pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Scanline_Time;
1387
1388 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1389 "State\\B%d\\FAX\\Disc Reason", nr);
1390 pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Disc_Reason;
1391
1392 pLib->fax_parse_entry_last[Channel] = pLib->cur_parse_entry - 1;
1393}
1394
1395static void diva_create_modem_parse_table (diva_strace_context_t* pLib,
1396 int Channel) {
1397 diva_trace_modem_state_t* pModem = &pLib->lines[Channel].modem;
1398 int nr = Channel+1;
1399
1400 if ((pLib->cur_parse_entry + MODEM_PARSE_ENTRIES) >= pLib->parse_entries) {
1401 diva_trace_error (pLib, -1, __FILE__, __LINE__);
1402 return;
1403 }
1404 pModem->ChannelNumber = nr;
1405
1406 pLib->modem_parse_entry_first[Channel] = pLib->cur_parse_entry;
1407
1408 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1409 "State\\B%d\\Modem\\Event", nr);
1410 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->Event;
1411
1412 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1413 "State\\B%d\\Modem\\Norm", nr);
1414 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->Norm;
1415
1416 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1417 "State\\B%d\\Modem\\Options", nr);
1418 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->Options;
1419
1420 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1421 "State\\B%d\\Modem\\TX Speed", nr);
1422 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->TxSpeed;
1423
1424 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1425 "State\\B%d\\Modem\\RX Speed", nr);
1426 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RxSpeed;
1427
1428 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1429 "State\\B%d\\Modem\\Roundtrip ms", nr);
1430 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RoundtripMsec;
1431
1432 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1433 "State\\B%d\\Modem\\Symbol Rate", nr);
1434 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->SymbolRate;
1435
1436 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1437 "State\\B%d\\Modem\\RX Level dBm", nr);
1438 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RxLeveldBm;
1439
1440 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1441 "State\\B%d\\Modem\\Echo Level dBm", nr);
1442 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->EchoLeveldBm;
1443
1444 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1445 "State\\B%d\\Modem\\SNR dB", nr);
1446 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->SNRdb;
1447
1448 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1449 "State\\B%d\\Modem\\MAE", nr);
1450 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->MAE;
1451
1452 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1453 "State\\B%d\\Modem\\Local Retrains", nr);
1454 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->LocalRetrains;
1455
1456 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1457 "State\\B%d\\Modem\\Remote Retrains", nr);
1458 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RemoteRetrains;
1459
1460 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1461 "State\\B%d\\Modem\\Local Resyncs", nr);
1462 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->LocalResyncs;
1463
1464 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1465 "State\\B%d\\Modem\\Remote Resyncs", nr);
1466 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RemoteResyncs;
1467
1468 sprintf (pLib->parse_table[pLib->cur_parse_entry].path,
1469 "State\\B%d\\Modem\\Disc Reason", nr);
1470 pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->DiscReason;
1471
1472 pLib->modem_parse_entry_last[Channel] = pLib->cur_parse_entry - 1;
1473}
1474
1475static void diva_create_parse_table (diva_strace_context_t* pLib) {
1476 int i;
1477
1478 for (i = 0; i < pLib->Channels; i++) {
1479 diva_create_line_parse_table (pLib, i);
1480 diva_create_modem_parse_table (pLib, i);
1481 diva_create_fax_parse_table (pLib, i);
1482 }
1483
1484 pLib->statistic_parse_first = pLib->cur_parse_entry;
1485
1486 /*
1487 Outgoing Calls
1488 */
1489 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1490 "Statistics\\Outgoing Calls\\Calls");
1491 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1492 &pLib->InterfaceStat.outg.Calls;
1493
1494 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1495 "Statistics\\Outgoing Calls\\Connected");
1496 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1497 &pLib->InterfaceStat.outg.Connected;
1498
1499 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1500 "Statistics\\Outgoing Calls\\User Busy");
1501 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1502 &pLib->InterfaceStat.outg.User_Busy;
1503
1504 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1505 "Statistics\\Outgoing Calls\\No Answer");
1506 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1507 &pLib->InterfaceStat.outg.No_Answer;
1508
1509 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1510 "Statistics\\Outgoing Calls\\Wrong Number");
1511 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1512 &pLib->InterfaceStat.outg.Wrong_Number;
1513
1514 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1515 "Statistics\\Outgoing Calls\\Call Rejected");
1516 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1517 &pLib->InterfaceStat.outg.Call_Rejected;
1518
1519 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1520 "Statistics\\Outgoing Calls\\Other Failures");
1521 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1522 &pLib->InterfaceStat.outg.Other_Failures;
1523
1524 /*
1525 Incoming Calls
1526 */
1527 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1528 "Statistics\\Incoming Calls\\Calls");
1529 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1530 &pLib->InterfaceStat.inc.Calls;
1531
1532 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1533 "Statistics\\Incoming Calls\\Connected");
1534 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1535 &pLib->InterfaceStat.inc.Connected;
1536
1537 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1538 "Statistics\\Incoming Calls\\User Busy");
1539 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1540 &pLib->InterfaceStat.inc.User_Busy;
1541
1542 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1543 "Statistics\\Incoming Calls\\Call Rejected");
1544 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1545 &pLib->InterfaceStat.inc.Call_Rejected;
1546
1547 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1548 "Statistics\\Incoming Calls\\Wrong Number");
1549 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1550 &pLib->InterfaceStat.inc.Wrong_Number;
1551
1552 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1553 "Statistics\\Incoming Calls\\Incompatible Dst");
1554 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1555 &pLib->InterfaceStat.inc.Incompatible_Dst;
1556
1557 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1558 "Statistics\\Incoming Calls\\Out of Order");
1559 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1560 &pLib->InterfaceStat.inc.Out_of_Order;
1561
1562 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1563 "Statistics\\Incoming Calls\\Ignored");
1564 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1565 &pLib->InterfaceStat.inc.Ignored;
1566
1567 /*
1568 Modem Statistics
1569 */
1570 pLib->mdm_statistic_parse_first = pLib->cur_parse_entry;
1571
1572 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1573 "Statistics\\Modem\\Disc Normal");
1574 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1575 &pLib->InterfaceStat.mdm.Disc_Normal;
1576
1577 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1578 "Statistics\\Modem\\Disc Unspecified");
1579 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1580 &pLib->InterfaceStat.mdm.Disc_Unspecified;
1581
1582 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1583 "Statistics\\Modem\\Disc Busy Tone");
1584 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1585 &pLib->InterfaceStat.mdm.Disc_Busy_Tone;
1586
1587 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1588 "Statistics\\Modem\\Disc Congestion");
1589 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1590 &pLib->InterfaceStat.mdm.Disc_Congestion;
1591
1592 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1593 "Statistics\\Modem\\Disc Carr. Wait");
1594 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1595 &pLib->InterfaceStat.mdm.Disc_Carr_Wait;
1596
1597 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1598 "Statistics\\Modem\\Disc Trn Timeout");
1599 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1600 &pLib->InterfaceStat.mdm.Disc_Trn_Timeout;
1601
1602 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1603 "Statistics\\Modem\\Disc Incompat.");
1604 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1605 &pLib->InterfaceStat.mdm.Disc_Incompat;
1606
1607 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1608 "Statistics\\Modem\\Disc Frame Rej.");
1609 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1610 &pLib->InterfaceStat.mdm.Disc_Frame_Rej;
1611
1612 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1613 "Statistics\\Modem\\Disc V42bis");
1614 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1615 &pLib->InterfaceStat.mdm.Disc_V42bis;
1616
1617 pLib->mdm_statistic_parse_last = pLib->cur_parse_entry - 1;
1618
1619 /*
1620 Fax Statistics
1621 */
1622 pLib->fax_statistic_parse_first = pLib->cur_parse_entry;
1623
1624 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1625 "Statistics\\FAX\\Disc Normal");
1626 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1627 &pLib->InterfaceStat.fax.Disc_Normal;
1628
1629 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1630 "Statistics\\FAX\\Disc Not Ident.");
1631 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1632 &pLib->InterfaceStat.fax.Disc_Not_Ident;
1633
1634 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1635 "Statistics\\FAX\\Disc No Response");
1636 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1637 &pLib->InterfaceStat.fax.Disc_No_Response;
1638
1639 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1640 "Statistics\\FAX\\Disc Retries");
1641 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1642 &pLib->InterfaceStat.fax.Disc_Retries;
1643
1644 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1645 "Statistics\\FAX\\Disc Unexp. Msg.");
1646 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1647 &pLib->InterfaceStat.fax.Disc_Unexp_Msg;
1648
1649 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1650 "Statistics\\FAX\\Disc No Polling.");
1651 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1652 &pLib->InterfaceStat.fax.Disc_No_Polling;
1653
1654 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1655 "Statistics\\FAX\\Disc Training");
1656 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1657 &pLib->InterfaceStat.fax.Disc_Training;
1658
1659 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1660 "Statistics\\FAX\\Disc Unexpected");
1661 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1662 &pLib->InterfaceStat.fax.Disc_Unexpected;
1663
1664 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1665 "Statistics\\FAX\\Disc Application");
1666 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1667 &pLib->InterfaceStat.fax.Disc_Application;
1668
1669 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1670 "Statistics\\FAX\\Disc Incompat.");
1671 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1672 &pLib->InterfaceStat.fax.Disc_Incompat;
1673
1674 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1675 "Statistics\\FAX\\Disc No Command");
1676 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1677 &pLib->InterfaceStat.fax.Disc_No_Command;
1678
1679 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1680 "Statistics\\FAX\\Disc Long Msg");
1681 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1682 &pLib->InterfaceStat.fax.Disc_Long_Msg;
1683
1684 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1685 "Statistics\\FAX\\Disc Supervisor");
1686 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1687 &pLib->InterfaceStat.fax.Disc_Supervisor;
1688
1689 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1690 "Statistics\\FAX\\Disc SUB SEP PWD");
1691 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1692 &pLib->InterfaceStat.fax.Disc_SUB_SEP_PWD;
1693
1694 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1695 "Statistics\\FAX\\Disc Invalid Msg");
1696 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1697 &pLib->InterfaceStat.fax.Disc_Invalid_Msg;
1698
1699 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1700 "Statistics\\FAX\\Disc Page Coding");
1701 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1702 &pLib->InterfaceStat.fax.Disc_Page_Coding;
1703
1704 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1705 "Statistics\\FAX\\Disc App Timeout");
1706 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1707 &pLib->InterfaceStat.fax.Disc_App_Timeout;
1708
1709 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1710 "Statistics\\FAX\\Disc Unspecified");
1711 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1712 &pLib->InterfaceStat.fax.Disc_Unspecified;
1713
1714 pLib->fax_statistic_parse_last = pLib->cur_parse_entry - 1;
1715
1716 /*
1717 B-Layer1"
1718 */
1719 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1720 "Statistics\\B-Layer1\\X-Frames");
1721 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1722 &pLib->InterfaceStat.b1.X_Frames;
1723
1724 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1725 "Statistics\\B-Layer1\\X-Bytes");
1726 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1727 &pLib->InterfaceStat.b1.X_Bytes;
1728
1729 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1730 "Statistics\\B-Layer1\\X-Errors");
1731 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1732 &pLib->InterfaceStat.b1.X_Errors;
1733
1734 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1735 "Statistics\\B-Layer1\\R-Frames");
1736 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1737 &pLib->InterfaceStat.b1.R_Frames;
1738
1739 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1740 "Statistics\\B-Layer1\\R-Bytes");
1741 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1742 &pLib->InterfaceStat.b1.R_Bytes;
1743
1744 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1745 "Statistics\\B-Layer1\\R-Errors");
1746 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1747 &pLib->InterfaceStat.b1.R_Errors;
1748
1749 /*
1750 B-Layer2
1751 */
1752 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1753 "Statistics\\B-Layer2\\X-Frames");
1754 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1755 &pLib->InterfaceStat.b2.X_Frames;
1756
1757 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1758 "Statistics\\B-Layer2\\X-Bytes");
1759 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1760 &pLib->InterfaceStat.b2.X_Bytes;
1761
1762 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1763 "Statistics\\B-Layer2\\X-Errors");
1764 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1765 &pLib->InterfaceStat.b2.X_Errors;
1766
1767 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1768 "Statistics\\B-Layer2\\R-Frames");
1769 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1770 &pLib->InterfaceStat.b2.R_Frames;
1771
1772 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1773 "Statistics\\B-Layer2\\R-Bytes");
1774 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1775 &pLib->InterfaceStat.b2.R_Bytes;
1776
1777 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1778 "Statistics\\B-Layer2\\R-Errors");
1779 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1780 &pLib->InterfaceStat.b2.R_Errors;
1781
1782 /*
1783 D-Layer1
1784 */
1785 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1786 "Statistics\\D-Layer1\\X-Frames");
1787 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1788 &pLib->InterfaceStat.d1.X_Frames;
1789
1790 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1791 "Statistics\\D-Layer1\\X-Bytes");
1792 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1793 &pLib->InterfaceStat.d1.X_Bytes;
1794
1795 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1796 "Statistics\\D-Layer1\\X-Errors");
1797 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1798 &pLib->InterfaceStat.d1.X_Errors;
1799
1800 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1801 "Statistics\\D-Layer1\\R-Frames");
1802 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1803 &pLib->InterfaceStat.d1.R_Frames;
1804
1805 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1806 "Statistics\\D-Layer1\\R-Bytes");
1807 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1808 &pLib->InterfaceStat.d1.R_Bytes;
1809
1810 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1811 "Statistics\\D-Layer1\\R-Errors");
1812 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1813 &pLib->InterfaceStat.d1.R_Errors;
1814
1815 /*
1816 D-Layer2
1817 */
1818 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1819 "Statistics\\D-Layer2\\X-Frames");
1820 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1821 &pLib->InterfaceStat.d2.X_Frames;
1822
1823 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1824 "Statistics\\D-Layer2\\X-Bytes");
1825 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1826 &pLib->InterfaceStat.d2.X_Bytes;
1827
1828 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1829 "Statistics\\D-Layer2\\X-Errors");
1830 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1831 &pLib->InterfaceStat.d2.X_Errors;
1832
1833 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1834 "Statistics\\D-Layer2\\R-Frames");
1835 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1836 &pLib->InterfaceStat.d2.R_Frames;
1837
1838 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1839 "Statistics\\D-Layer2\\R-Bytes");
1840 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1841 &pLib->InterfaceStat.d2.R_Bytes;
1842
1843 strcpy (pLib->parse_table[pLib->cur_parse_entry].path,
1844 "Statistics\\D-Layer2\\R-Errors");
1845 pLib->parse_table[pLib->cur_parse_entry++].variable = \
1846 &pLib->InterfaceStat.d2.R_Errors;
1847
1848
1849 pLib->statistic_parse_last = pLib->cur_parse_entry - 1;
1850}
1851
1852static void diva_trace_error (diva_strace_context_t* pLib,
1853 int error, const char* file, int line) {
1854 if (pLib->user_proc_table.error_notify_proc) {
1855 (*(pLib->user_proc_table.error_notify_proc))(\
1856 pLib->user_proc_table.user_context,
1857 &pLib->instance, pLib->Adapter,
1858 error, file, line);
1859 }
1860}
1861
1862/*
1863 Delivery notification to user
1864 */
1865static void diva_trace_notify_user (diva_strace_context_t* pLib,
1866 int Channel,
1867 int notify_subject) {
1868 if (pLib->user_proc_table.notify_proc) {
1869 (*(pLib->user_proc_table.notify_proc))(pLib->user_proc_table.user_context,
1870 &pLib->instance,
1871 pLib->Adapter,
1872 &pLib->lines[Channel],
1873 notify_subject);
1874 }
1875}
1876
1877/*
1878 Read variable value to they destination based on the variable type
1879 */
1880static int diva_trace_read_variable (diva_man_var_header_t* pVar,
1881 void* variable) {
1882 switch (pVar->type) {
1883 case 0x03: /* MI_ASCIIZ - syting */
1884 return (diva_strace_read_asz (pVar, (char*)variable));
1885 case 0x04: /* MI_ASCII - string */
1886 return (diva_strace_read_asc (pVar, (char*)variable));
1887 case 0x05: /* MI_NUMBER - counted sequence of bytes */
1888 return (diva_strace_read_ie (pVar, (diva_trace_ie_t*)variable));
1889 case 0x81: /* MI_INT - signed integer */
1890 return (diva_strace_read_int (pVar, (int*)variable));
1891 case 0x82: /* MI_UINT - unsigned integer */
1892 return (diva_strace_read_uint (pVar, (dword*)variable));
1893 case 0x83: /* MI_HINT - unsigned integer, hex representetion */
1894 return (diva_strace_read_uint (pVar, (dword*)variable));
1895 case 0x87: /* MI_BITFLD - unsigned integer, bit representation */
1896 return (diva_strace_read_uint (pVar, (dword*)variable));
1897 }
1898
1899 /*
1900 This type of variable is not handled, indicate error
1901 Or one problem in management interface, or in application recodeing
1902 table, or this application should handle it.
1903 */
1904 return (-1);
1905}
1906
1907/*
1908 Read signed integer to destination
1909 */
1910static int diva_strace_read_int (diva_man_var_header_t* pVar, int* var) {
1911 byte* ptr = (char*)&pVar->path_length;
1912 int value;
1913
1914 ptr += (pVar->path_length + 1);
1915
1916 switch (pVar->value_length) {
1917 case 1:
1918 value = *(char*)ptr;
1919 break;
1920
1921 case 2:
1922 value = (short)GET_WORD(ptr);
1923 break;
1924
1925 case 4:
1926 value = (int)GET_DWORD(ptr);
1927 break;
1928
1929 default:
1930 return (-1);
1931 }
1932
1933 *var = value;
1934
1935 return (0);
1936}
1937
1938static int diva_strace_read_uint (diva_man_var_header_t* pVar, dword* var) {
1939 byte* ptr = (char*)&pVar->path_length;
1940 dword value;
1941
1942 ptr += (pVar->path_length + 1);
1943
1944 switch (pVar->value_length) {
1945 case 1:
1946 value = (byte)(*ptr);
1947 break;
1948
1949 case 2:
1950 value = (word)GET_WORD(ptr);
1951 break;
1952
1953 case 3:
1954 value = (dword)GET_DWORD(ptr);
1955 value &= 0x00ffffff;
1956 break;
1957
1958 case 4:
1959 value = (dword)GET_DWORD(ptr);
1960 break;
1961
1962 default:
1963 return (-1);
1964 }
1965
1966 *var = value;
1967
1968 return (0);
1969}
1970
1971/*
1972 Read zero terminated ASCII string
1973 */
1974static int diva_strace_read_asz (diva_man_var_header_t* pVar, char* var) {
1975 char* ptr = (char*)&pVar->path_length;
1976 int length;
1977
1978 ptr += (pVar->path_length + 1);
1979
1980 if (!(length = pVar->value_length)) {
1981 length = strlen (ptr);
1982 }
1983 memcpy (var, ptr, length);
1984 var[length] = 0;
1985
1986 return (0);
1987}
1988
1989/*
1990 Read counted (with leading length byte) ASCII string
1991 */
1992static int diva_strace_read_asc (diva_man_var_header_t* pVar, char* var) {
1993 char* ptr = (char*)&pVar->path_length;
1994
1995 ptr += (pVar->path_length + 1);
1996 memcpy (var, ptr+1, *ptr);
1997 var[(int)*ptr] = 0;
1998
1999 return (0);
2000}
2001
2002/*
2003 Read one information element - i.e. one string of byte values with
2004 one length byte in front
2005 */
2006static int diva_strace_read_ie (diva_man_var_header_t* pVar,
2007 diva_trace_ie_t* var) {
2008 char* ptr = (char*)&pVar->path_length;
2009
2010 ptr += (pVar->path_length + 1);
2011
2012 var->length = *ptr;
2013 memcpy (&var->data[0], ptr+1, *ptr);
2014
2015 return (0);
2016}
2017
2018static int SuperTraceSetAudioTap (void* hLib, int Channel, int on) {
2019 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
2020
2021 if ((Channel < 1) || (Channel > pLib->Channels)) {
2022 return (-1);
2023 }
2024 Channel--;
2025
2026 if (on) {
2027 pLib->audio_tap_mask |= (1L << Channel);
2028 } else {
2029 pLib->audio_tap_mask &= ~(1L << Channel);
2030 }
2031
2032 /*
2033 EYE patterns have TM_M_DATA set as additional
2034 condition
2035 */
2036 if (pLib->audio_tap_mask) {
2037 pLib->trace_event_mask |= TM_M_DATA;
2038 } else {
2039 pLib->trace_event_mask &= ~TM_M_DATA;
2040 }
2041
2042 return (ScheduleNextTraceRequest (pLib));
2043}
2044
2045static int SuperTraceSetBChannel (void* hLib, int Channel, int on) {
2046 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
2047
2048 if ((Channel < 1) || (Channel > pLib->Channels)) {
2049 return (-1);
2050 }
2051 Channel--;
2052
2053 if (on) {
2054 pLib->bchannel_trace_mask |= (1L << Channel);
2055 } else {
2056 pLib->bchannel_trace_mask &= ~(1L << Channel);
2057 }
2058
2059 return (ScheduleNextTraceRequest (pLib));
2060}
2061
2062static int SuperTraceSetDChannel (void* hLib, int on) {
2063 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
2064
2065 if (on) {
2066 pLib->trace_event_mask |= (TM_D_CHAN | TM_C_COMM | TM_DL_ERR | TM_LAYER1);
2067 } else {
2068 pLib->trace_event_mask &= ~(TM_D_CHAN | TM_C_COMM | TM_DL_ERR | TM_LAYER1);
2069 }
2070
2071 return (ScheduleNextTraceRequest (pLib));
2072}
2073
2074static int SuperTraceSetInfo (void* hLib, int on) {
2075 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
2076
2077 if (on) {
2078 pLib->trace_event_mask |= TM_STRING;
2079 } else {
2080 pLib->trace_event_mask &= ~TM_STRING;
2081 }
2082
2083 return (ScheduleNextTraceRequest (pLib));
2084}
2085
2086static int SuperTraceClearCall (void* hLib, int Channel) {
2087 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
2088
2089 if ((Channel < 1) || (Channel > pLib->Channels)) {
2090 return (-1);
2091 }
2092 Channel--;
2093
2094 pLib->clear_call_command |= (1L << Channel);
2095
2096 return (ScheduleNextTraceRequest (pLib));
2097}
2098
2099/*
2100 Parse and update cumulative statistice
2101 */
2102static int diva_ifc_statistics (diva_strace_context_t* pLib,
2103 diva_man_var_header_t* pVar) {
2104 diva_man_var_header_t* cur;
2105 int i, one_updated = 0, mdm_updated = 0, fax_updated = 0;
2106
2107 for (i = pLib->statistic_parse_first; i <= pLib->statistic_parse_last; i++) {
2108 if ((cur = find_var (pVar, pLib->parse_table[i].path))) {
2109 if (diva_trace_read_variable (cur, pLib->parse_table[i].variable)) {
2110 diva_trace_error (pLib, -3 , __FILE__, __LINE__);
2111 return (-1);
2112 }
2113 one_updated = 1;
2114 if ((i >= pLib->mdm_statistic_parse_first) && (i <= pLib->mdm_statistic_parse_last)) {
2115 mdm_updated = 1;
2116 }
2117 if ((i >= pLib->fax_statistic_parse_first) && (i <= pLib->fax_statistic_parse_last)) {
2118 fax_updated = 1;
2119 }
2120 }
2121 }
2122
2123 /*
2124 We do not use first event to notify user - this is the event that is
2125 generated as result of EVENT ON operation and is used only to initialize
2126 internal variables of application
2127 */
2128 if (mdm_updated) {
2129 diva_trace_notify_user (pLib, 0, DIVA_SUPER_TRACE_NOTIFY_MDM_STAT_CHANGE);
2130 } else if (fax_updated) {
2131 diva_trace_notify_user (pLib, 0, DIVA_SUPER_TRACE_NOTIFY_FAX_STAT_CHANGE);
2132 } else if (one_updated) {
2133 diva_trace_notify_user (pLib, 0, DIVA_SUPER_TRACE_NOTIFY_STAT_CHANGE);
2134 }
2135
2136 return (one_updated ? 0 : -1);
2137}
2138
2139static int SuperTraceGetOutgoingCallStatistics (void* hLib) {
2140 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
2141 pLib->outgoing_ifc_stats = 1;
2142 return (ScheduleNextTraceRequest (pLib));
2143}
2144
2145static int SuperTraceGetIncomingCallStatistics (void* hLib) {
2146 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
2147 pLib->incoming_ifc_stats = 1;
2148 return (ScheduleNextTraceRequest (pLib));
2149}
2150
2151static int SuperTraceGetModemStatistics (void* hLib) {
2152 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
2153 pLib->modem_ifc_stats = 1;
2154 return (ScheduleNextTraceRequest (pLib));
2155}
2156
2157static int SuperTraceGetFaxStatistics (void* hLib) {
2158 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
2159 pLib->fax_ifc_stats = 1;
2160 return (ScheduleNextTraceRequest (pLib));
2161}
2162
2163static int SuperTraceGetBLayer1Statistics (void* hLib) {
2164 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
2165 pLib->b1_ifc_stats = 1;
2166 return (ScheduleNextTraceRequest (pLib));
2167}
2168
2169static int SuperTraceGetBLayer2Statistics (void* hLib) {
2170 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
2171 pLib->b2_ifc_stats = 1;
2172 return (ScheduleNextTraceRequest (pLib));
2173}
2174
2175static int SuperTraceGetDLayer1Statistics (void* hLib) {
2176 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
2177 pLib->d1_ifc_stats = 1;
2178 return (ScheduleNextTraceRequest (pLib));
2179}
2180
2181static int SuperTraceGetDLayer2Statistics (void* hLib) {
2182 diva_strace_context_t* pLib = (diva_strace_context_t*)hLib;
2183 pLib->d2_ifc_stats = 1;
2184 return (ScheduleNextTraceRequest (pLib));
2185}
2186
2187dword DivaSTraceGetMemotyRequirement (int channels) {
2188 dword parse_entries = (MODEM_PARSE_ENTRIES + FAX_PARSE_ENTRIES + \
2189 STAT_PARSE_ENTRIES + \
2190 LINE_PARSE_ENTRIES + 1) * channels;
2191 return (sizeof(diva_strace_context_t) + \
2192 (parse_entries * sizeof(diva_strace_path2action_t)));
2193}
2194
diff --git a/drivers/isdn/hardware/eicon/maintidi.h b/drivers/isdn/hardware/eicon/maintidi.h
new file mode 100644
index 000000000000..4f06294966b8
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/maintidi.h
@@ -0,0 +1,172 @@
1/*
2 *
3 Copyright (c) Eicon Networks, 2000.
4 *
5 This source file is supplied for the use with
6 Eicon Networks range of DIVA Server Adapters.
7 *
8 Eicon File Revision : 1.9
9 *
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14 *
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License for more details.
19 *
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25#ifndef __DIVA_EICON_TRACE_IDI_IFC_H__
26#define __DIVA_EICON_TRACE_IDI_IFC_H__
27
28void* SuperTraceOpenAdapter (int AdapterNumber);
29int SuperTraceCloseAdapter (void* AdapterHandle);
30int SuperTraceWrite (void* AdapterHandle,
31 const void* data, int length);
32int SuperTraceReadRequest (void* AdapterHandle,const char* name,byte* data);
33int SuperTraceGetNumberOfChannels (void* AdapterHandle);
34int SuperTraceASSIGN (void* AdapterHandle, byte* data);
35int SuperTraceREMOVE (void* AdapterHandle);
36int SuperTraceTraceOnRequest(void* hAdapter, const char* name, byte* data);
37int SuperTraceWriteVar (void* AdapterHandle,
38 byte* data,
39 const char* name,
40 void* var,
41 byte type,
42 byte var_length);
43int SuperTraceExecuteRequest (void* AdapterHandle,
44 const char* name,
45 byte* data);
46
47typedef struct _diva_strace_path2action {
48 char path[64]; /* Full path to variable */
49 void* variable; /* Variable that will receive value */
50} diva_strace_path2action_t;
51
52#define DIVA_MAX_MANAGEMENT_TRANSFER_SIZE 4096
53
54typedef struct _diva_strace_context {
55 diva_strace_library_interface_t instance;
56
57 int Adapter;
58 void* hAdapter;
59
60 int Channels;
61 int req_busy;
62
63 ENTITY e;
64 IDI_CALL request;
65 BUFFERS XData;
66 BUFFERS RData;
67 byte buffer[DIVA_MAX_MANAGEMENT_TRANSFER_SIZE + 1];
68 int removal_state;
69 int general_b_ch_event;
70 int general_fax_event;
71 int general_mdm_event;
72
73 byte rc_ok;
74
75 /*
76 Initialization request state machine
77 */
78 int ChannelsTraceActive;
79 int ModemTraceActive;
80 int FaxTraceActive;
81 int IncomingCallsCallsActive;
82 int IncomingCallsConnectedActive;
83 int OutgoingCallsCallsActive;
84 int OutgoingCallsConnectedActive;
85
86 int trace_mask_init;
87 int audio_trace_init;
88 int bchannel_init;
89 int trace_length_init;
90 int trace_on;
91 int trace_events_down;
92 int l1_trace;
93 int l2_trace;
94
95 /*
96 Trace\Event Enable
97 */
98 word trace_event_mask;
99 word current_trace_event_mask;
100
101 dword audio_tap_mask;
102 dword current_audio_tap_mask;
103 dword current_eye_pattern_mask;
104 int audio_tap_pending;
105 int eye_pattern_pending;
106
107 dword bchannel_trace_mask;
108 dword current_bchannel_trace_mask;
109
110
111 diva_trace_line_state_t lines[30];
112
113 int parse_entries;
114 int cur_parse_entry;
115 diva_strace_path2action_t* parse_table;
116
117 diva_trace_library_user_interface_t user_proc_table;
118
119 int line_parse_entry_first[30];
120 int line_parse_entry_last[30];
121
122 int modem_parse_entry_first[30];
123 int modem_parse_entry_last[30];
124
125 int fax_parse_entry_first[30];
126 int fax_parse_entry_last[30];
127
128 int statistic_parse_first;
129 int statistic_parse_last;
130
131 int mdm_statistic_parse_first;
132 int mdm_statistic_parse_last;
133
134 int fax_statistic_parse_first;
135 int fax_statistic_parse_last;
136
137 dword line_init_event;
138 dword modem_init_event;
139 dword fax_init_event;
140
141 dword pending_line_status;
142 dword pending_modem_status;
143 dword pending_fax_status;
144
145 dword clear_call_command;
146
147 int outgoing_ifc_stats;
148 int incoming_ifc_stats;
149 int modem_ifc_stats;
150 int fax_ifc_stats;
151 int b1_ifc_stats;
152 int b2_ifc_stats;
153 int d1_ifc_stats;
154 int d2_ifc_stats;
155
156 diva_trace_interface_state_t Interface;
157 diva_ifc_statistics_t InterfaceStat;
158} diva_strace_context_t;
159
160typedef struct _diva_man_var_header {
161 byte escape;
162 byte length;
163 byte management_id;
164 byte type;
165 byte attribute;
166 byte status;
167 byte value_length;
168 byte path_length;
169} diva_man_var_header_t;
170
171#endif
172
diff --git a/drivers/isdn/hardware/eicon/man_defs.h b/drivers/isdn/hardware/eicon/man_defs.h
new file mode 100644
index 000000000000..cb4ef4cae6c1
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/man_defs.h
@@ -0,0 +1,133 @@
1/*
2 *
3 Copyright (c) Eicon Networks, 2002.
4 *
5 This source file is supplied for the use with
6 Eicon Networks range of DIVA Server Adapters.
7 *
8 Eicon File Revision : 1.9
9 *
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14 *
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License for more details.
19 *
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25/* Definitions for use with the Management Information Element */
26
27/*------------------------------------------------------------------*/
28/* Management information element */
29/* ---------------------------------------------------------- */
30/* Byte Coding Comment */
31/* ---------------------------------------------------------- */
32/* 0 | 0 1 1 1 1 1 1 1 | ESC */
33/* 1 | 0 x x x x x x x | Length of information element (m-1) */
34/* 2 | 1 0 0 0 0 0 0 0 | Management Information Id */
35/* 3 | x x x x x x x x | Type */
36/* 4 | x x x x x x x x | Attribute */
37/* 5 | x x x x x x x x | Status */
38/* 6 | x x x x x x x x | Variable Value Length (m-n) */
39/* 7 | x x x x x x x x | Path / Variable Name String Length (n-8)*/
40/* 8..n | x x x x x x x x | Path/Node Name String separated by '\' */
41/* n..m | x x x x x x x x | Variable content */
42/*------------------------------------------------------------------*/
43
44/*------------------------------------------------------------------*/
45/* Type Field */
46/* */
47/* MAN_READ: not used */
48/* MAN_WRITE: not used */
49/* MAN_EVENT_ON: not used */
50/* MAN_EVENT_OFF: not used */
51/* MAN_INFO_IND: type of variable */
52/* MAN_EVENT_IND: type of variable */
53/* MAN_TRACE_IND not used */
54/*------------------------------------------------------------------*/
55#define MI_DIR 0x01 /* Directory string (zero terminated) */
56#define MI_EXECUTE 0x02 /* Executable function (has no value) */
57#define MI_ASCIIZ 0x03 /* Zero terminated string */
58#define MI_ASCII 0x04 /* String, first byte is length */
59#define MI_NUMBER 0x05 /* Number string, first byte is length*/
60#define MI_TRACE 0x06 /* Trace information, format see below*/
61
62#define MI_FIXED_LENGTH 0x80 /* get length from MAN_INFO max_len */
63#define MI_INT 0x81 /* number to display as signed int */
64#define MI_UINT 0x82 /* number to display as unsigned int */
65#define MI_HINT 0x83 /* number to display in hex format */
66#define MI_HSTR 0x84 /* number to display as a hex string */
67#define MI_BOOLEAN 0x85 /* number to display as boolean */
68#define MI_IP_ADDRESS 0x86 /* number to display as IP address */
69#define MI_BITFLD 0x87 /* number to display as bit field */
70#define MI_SPID_STATE 0x88 /* state# of SPID initialisation */
71
72/*------------------------------------------------------------------*/
73/* Attribute Field */
74/* */
75/* MAN_READ: not used */
76/* MAN_WRITE: not used */
77/* MAN_EVENT_ON: not used */
78/* MAN_EVENT_OFF: not used */
79/* MAN_INFO_IND: set according to capabilities of that variable */
80/* MAN_EVENT_IND: not used */
81/* MAN_TRACE_IND not used */
82/*------------------------------------------------------------------*/
83#define MI_WRITE 0x01 /* Variable is writeable */
84#define MI_EVENT 0x02 /* Variable can indicate changes */
85
86/*------------------------------------------------------------------*/
87/* Status Field */
88/* */
89/* MAN_READ: not used */
90/* MAN_WRITE: not used */
91/* MAN_EVENT_ON: not used */
92/* MAN_EVENT_OFF: not used */
93/* MAN_INFO_IND: set according to the actual status */
94/* MAN_EVENT_IND: set according to the actual statu */
95/* MAN_TRACE_IND not used */
96/*------------------------------------------------------------------*/
97#define MI_LOCKED 0x01 /* write protected by another instance*/
98#define MI_EVENT_ON 0x02 /* Event logging switched on */
99#define MI_PROTECTED 0x04 /* write protected by this instance */
100
101/*------------------------------------------------------------------*/
102/* Data Format used for MAN_TRACE_IND (no MI-element used) */
103/*------------------------------------------------------------------*/
104typedef struct mi_xlog_hdr_s MI_XLOG_HDR;
105struct mi_xlog_hdr_s
106{
107 unsigned long time; /* Timestamp in msec units */
108 unsigned short size; /* Size of data that follows */
109 unsigned short code; /* code of trace event */
110}; /* unspecified data follows this header */
111
112/*------------------------------------------------------------------*/
113/* Trace mask definitions for trace events except B channel and */
114/* debug trace events */
115/*------------------------------------------------------------------*/
116#define TM_D_CHAN 0x0001 /* D-Channel (D-.) Code 3,4 */
117#define TM_L_LAYER 0x0002 /* Low Layer (LL) Code 6,7 */
118#define TM_N_LAYER 0x0004 /* Network Layer (N) Code 14,15 */
119#define TM_DL_ERR 0x0008 /* Data Link Error (MDL) Code 9 */
120#define TM_LAYER1 0x0010 /* Layer 1 Code 20 */
121#define TM_C_COMM 0x0020 /* Call Comment (SIG) Code 5,21,22 */
122#define TM_M_DATA 0x0040 /* Modulation Data (EYE) Code 23 */
123#define TM_STRING 0x0080 /* Sting data Code 24 */
124#define TM_N_USED2 0x0100 /* not used */
125#define TM_N_USED3 0x0200 /* not used */
126#define TM_N_USED4 0x0400 /* not used */
127#define TM_N_USED5 0x0800 /* not used */
128#define TM_N_USED6 0x1000 /* not used */
129#define TM_N_USED7 0x2000 /* not used */
130#define TM_N_USED8 0x4000 /* not used */
131#define TM_REST 0x8000 /* Codes 10,11,12,13,16,18,19,128,129 */
132
133/*------ End of file -----------------------------------------------*/
diff --git a/drivers/isdn/hardware/eicon/mdm_msg.h b/drivers/isdn/hardware/eicon/mdm_msg.h
new file mode 100644
index 000000000000..7a737e10bce0
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/mdm_msg.h
@@ -0,0 +1,346 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef __EICON_MDM_MSG_H__
27#define __EICON_MDM_MSG_H__
28#define DSP_UDATA_INDICATION_DCD_OFF 0x01
29#define DSP_UDATA_INDICATION_DCD_ON 0x02
30#define DSP_UDATA_INDICATION_CTS_OFF 0x03
31#define DSP_UDATA_INDICATION_CTS_ON 0x04
32/* =====================================================================
33DCD_OFF Message:
34 <word> time of DCD off (sampled from counter at 8kHz)
35DCD_ON Message:
36 <word> time of DCD on (sampled from counter at 8kHz)
37 <byte> connected norm
38 <word> connected options
39 <dword> connected speed (bit/s, max of tx and rx speed)
40 <word> roundtrip delay (ms)
41 <dword> connected speed tx (bit/s)
42 <dword> connected speed rx (bit/s)
43 Size of this message == 19 bytes, but we will receive only 11
44 ===================================================================== */
45#define DSP_CONNECTED_NORM_UNSPECIFIED 0
46#define DSP_CONNECTED_NORM_V21 1
47#define DSP_CONNECTED_NORM_V23 2
48#define DSP_CONNECTED_NORM_V22 3
49#define DSP_CONNECTED_NORM_V22_BIS 4
50#define DSP_CONNECTED_NORM_V32_BIS 5
51#define DSP_CONNECTED_NORM_V34 6
52#define DSP_CONNECTED_NORM_V8 7
53#define DSP_CONNECTED_NORM_BELL_212A 8
54#define DSP_CONNECTED_NORM_BELL_103 9
55#define DSP_CONNECTED_NORM_V29_LEASED_LINE 10
56#define DSP_CONNECTED_NORM_V33_LEASED_LINE 11
57#define DSP_CONNECTED_NORM_V90 12
58#define DSP_CONNECTED_NORM_V21_CH2 13
59#define DSP_CONNECTED_NORM_V27_TER 14
60#define DSP_CONNECTED_NORM_V29 15
61#define DSP_CONNECTED_NORM_V33 16
62#define DSP_CONNECTED_NORM_V17 17
63#define DSP_CONNECTED_NORM_V32 18
64#define DSP_CONNECTED_NORM_K56_FLEX 19
65#define DSP_CONNECTED_NORM_X2 20
66#define DSP_CONNECTED_NORM_V18 21
67#define DSP_CONNECTED_NORM_V18_LOW_HIGH 22
68#define DSP_CONNECTED_NORM_V18_HIGH_LOW 23
69#define DSP_CONNECTED_NORM_V21_LOW_HIGH 24
70#define DSP_CONNECTED_NORM_V21_HIGH_LOW 25
71#define DSP_CONNECTED_NORM_BELL103_LOW_HIGH 26
72#define DSP_CONNECTED_NORM_BELL103_HIGH_LOW 27
73#define DSP_CONNECTED_NORM_V23_75_1200 28
74#define DSP_CONNECTED_NORM_V23_1200_75 29
75#define DSP_CONNECTED_NORM_EDT_110 30
76#define DSP_CONNECTED_NORM_BAUDOT_45 31
77#define DSP_CONNECTED_NORM_BAUDOT_47 32
78#define DSP_CONNECTED_NORM_BAUDOT_50 33
79#define DSP_CONNECTED_NORM_DTMF 34
80#define DSP_CONNECTED_NORM_V18_RESERVED_13 35
81#define DSP_CONNECTED_NORM_V18_RESERVED_14 36
82#define DSP_CONNECTED_NORM_V18_RESERVED_15 37
83#define DSP_CONNECTED_NORM_VOWN 38
84#define DSP_CONNECTED_NORM_V23_OFF_HOOK 39
85#define DSP_CONNECTED_NORM_V23_ON_HOOK 40
86#define DSP_CONNECTED_NORM_VOWN_RESERVED_3 41
87#define DSP_CONNECTED_NORM_VOWN_RESERVED_4 42
88#define DSP_CONNECTED_NORM_VOWN_RESERVED_5 43
89#define DSP_CONNECTED_NORM_VOWN_RESERVED_6 44
90#define DSP_CONNECTED_NORM_VOWN_RESERVED_7 45
91#define DSP_CONNECTED_NORM_VOWN_RESERVED_8 46
92#define DSP_CONNECTED_NORM_VOWN_RESERVED_9 47
93#define DSP_CONNECTED_NORM_VOWN_RESERVED_10 48
94#define DSP_CONNECTED_NORM_VOWN_RESERVED_11 49
95#define DSP_CONNECTED_NORM_VOWN_RESERVED_12 50
96#define DSP_CONNECTED_NORM_VOWN_RESERVED_13 51
97#define DSP_CONNECTED_NORM_VOWN_RESERVED_14 52
98#define DSP_CONNECTED_NORM_VOWN_RESERVED_15 53
99#define DSP_CONNECTED_NORM_VOWN_RESERVED_16 54
100#define DSP_CONNECTED_NORM_VOWN_RESERVED_17 55
101#define DSP_CONNECTED_NORM_VOWN_RESERVED_18 56
102#define DSP_CONNECTED_NORM_VOWN_RESERVED_19 57
103#define DSP_CONNECTED_NORM_VOWN_RESERVED_20 58
104#define DSP_CONNECTED_NORM_VOWN_RESERVED_21 59
105#define DSP_CONNECTED_NORM_VOWN_RESERVED_22 60
106#define DSP_CONNECTED_NORM_VOWN_RESERVED_23 61
107#define DSP_CONNECTED_NORM_VOWN_RESERVED_24 62
108#define DSP_CONNECTED_NORM_VOWN_RESERVED_25 63
109#define DSP_CONNECTED_NORM_VOWN_RESERVED_26 64
110#define DSP_CONNECTED_NORM_VOWN_RESERVED_27 65
111#define DSP_CONNECTED_NORM_VOWN_RESERVED_28 66
112#define DSP_CONNECTED_NORM_VOWN_RESERVED_29 67
113#define DSP_CONNECTED_NORM_VOWN_RESERVED_30 68
114#define DSP_CONNECTED_NORM_VOWN_RESERVED_31 69
115#define DSP_CONNECTED_OPTION_TRELLIS 0x0001
116#define DSP_CONNECTED_OPTION_V42_TRANS 0x0002
117#define DSP_CONNECTED_OPTION_V42_LAPM 0x0004
118#define DSP_CONNECTED_OPTION_SHORT_TRAIN 0x0008
119#define DSP_CONNECTED_OPTION_TALKER_ECHO_PROTECT 0x0010
120#define DSP_CONNECTED_OPTION_V42BIS 0x0020
121#define DSP_CONNECTED_OPTION_MNP2 0x0040
122#define DSP_CONNECTED_OPTION_MNP3 0x0080
123#define DSP_CONNECTED_OPTION_MNP4 0x00c0
124#define DSP_CONNECTED_OPTION_MNP5 0x0100
125#define DSP_CONNECTED_OPTION_MNP10 0x0200
126#define DSP_CONNECTED_OPTION_MASK_V42 0x0024
127#define DSP_CONNECTED_OPTION_MASK_MNP 0x03c0
128#define DSP_CONNECTED_OPTION_MASK_ERROR_CORRECT 0x03e4
129#define DSP_CONNECTED_OPTION_MASK_COMPRESSION 0x0320
130#define DSP_UDATA_INDICATION_DISCONNECT 5
131/*
132returns:
133 <byte> cause
134*/
135/* ==========================================================
136 DLC: B2 modem configuration
137 ========================================================== */
138/*
139Fields in assign DLC information element for modem protocol V.42/MNP:
140 <byte> length of information element
141 <word> information field length
142 <byte> address A (not used, default 3)
143 <byte> address B (not used, default 1)
144 <byte> modulo mode (not used, default 7)
145 <byte> window size (not used, default 7)
146 <word> XID length (not used, default 0)
147 ... XID information (not used, default empty)
148 <byte> modem protocol negotiation options
149 <byte> modem protocol options
150 <byte> modem protocol break configuration
151 <byte> modem protocol application options
152*/
153#define DLC_MODEMPROT_DISABLE_V42_V42BIS 0x01
154#define DLC_MODEMPROT_DISABLE_MNP_MNP5 0x02
155#define DLC_MODEMPROT_REQUIRE_PROTOCOL 0x04
156#define DLC_MODEMPROT_DISABLE_V42_DETECT 0x08
157#define DLC_MODEMPROT_DISABLE_COMPRESSION 0x10
158#define DLC_MODEMPROT_REQUIRE_PROTOCOL_V34UP 0x20
159#define DLC_MODEMPROT_NO_PROTOCOL_IF_1200 0x01
160#define DLC_MODEMPROT_BUFFER_IN_V42_DETECT 0x02
161#define DLC_MODEMPROT_DISABLE_V42_SREJ 0x04
162#define DLC_MODEMPROT_DISABLE_MNP3 0x08
163#define DLC_MODEMPROT_DISABLE_MNP4 0x10
164#define DLC_MODEMPROT_DISABLE_MNP10 0x20
165#define DLC_MODEMPROT_NO_PROTOCOL_IF_V22BIS 0x40
166#define DLC_MODEMPROT_NO_PROTOCOL_IF_V32BIS 0x80
167#define DLC_MODEMPROT_BREAK_DISABLED 0x00
168#define DLC_MODEMPROT_BREAK_NORMAL 0x01
169#define DLC_MODEMPROT_BREAK_EXPEDITED 0x02
170#define DLC_MODEMPROT_BREAK_DESTRUCTIVE 0x03
171#define DLC_MODEMPROT_BREAK_CONFIG_MASK 0x03
172#define DLC_MODEMPROT_APPL_EARLY_CONNECT 0x01
173#define DLC_MODEMPROT_APPL_PASS_INDICATIONS 0x02
174/* ==========================================================
175 CAI parameters used for the modem L1 configuration
176 ========================================================== */
177/*
178Fields in assign CAI information element:
179 <byte> length of information element
180 <byte> info field and B-channel hardware
181 <byte> rate adaptation bit rate
182 <byte> async framing parameters
183 <byte> reserved
184 <word> packet length
185 <byte> modem line taking options
186 <byte> modem modulation negotiation parameters
187 <byte> modem modulation options
188 <byte> modem disabled modulations mask low
189 <byte> modem disabled modulations mask high
190 <byte> modem enabled modulations mask
191 <word> modem min TX speed
192 <word> modem max TX speed
193 <word> modem min RX speed
194 <word> modem max RX speed
195 <byte> modem disabled symbol rates mask
196 <byte> modem info options mask
197 <byte> modem transmit level adjust
198 <byte> modem speaker parameters
199 <word> modem private debug config
200 <struct> modem reserved
201 <struct> v18 config parameters
202 <struct> v18 probing sequence
203 <struct> v18 probing message
204*/
205#define DSP_CAI_HARDWARE_HDLC_64K 0x05
206#define DSP_CAI_HARDWARE_HDLC_56K 0x08
207#define DSP_CAI_HARDWARE_TRANSP 0x09
208#define DSP_CAI_HARDWARE_V110_SYNC 0x0c
209#define DSP_CAI_HARDWARE_V110_ASYNC 0x0d
210#define DSP_CAI_HARDWARE_HDLC_128K 0x0f
211#define DSP_CAI_HARDWARE_FAX 0x10
212#define DSP_CAI_HARDWARE_MODEM_ASYNC 0x11
213#define DSP_CAI_HARDWARE_MODEM_SYNC 0x12
214#define DSP_CAI_HARDWARE_V110_HDLCA 0x13
215#define DSP_CAI_HARDWARE_ADVANCED_VOICE 0x14
216#define DSP_CAI_HARDWARE_TRANSP_DTMF 0x16
217#define DSP_CAI_HARDWARE_DTMF_VOICE_ISDN 0x17
218#define DSP_CAI_HARDWARE_DTMF_VOICE_LOCAL 0x18
219#define DSP_CAI_HARDWARE_MASK 0x3f
220#define DSP_CAI_ENABLE_INFO_INDICATIONS 0x80
221#define DSP_CAI_RATE_ADAPTATION_300 0x00
222#define DSP_CAI_RATE_ADAPTATION_600 0x01
223#define DSP_CAI_RATE_ADAPTATION_1200 0x02
224#define DSP_CAI_RATE_ADAPTATION_2400 0x03
225#define DSP_CAI_RATE_ADAPTATION_4800 0x04
226#define DSP_CAI_RATE_ADAPTATION_9600 0x05
227#define DSP_CAI_RATE_ADAPTATION_19200 0x06
228#define DSP_CAI_RATE_ADAPTATION_38400 0x07
229#define DSP_CAI_RATE_ADAPTATION_48000 0x08
230#define DSP_CAI_RATE_ADAPTATION_56000 0x09
231#define DSP_CAI_RATE_ADAPTATION_7200 0x0a
232#define DSP_CAI_RATE_ADAPTATION_14400 0x0b
233#define DSP_CAI_RATE_ADAPTATION_28800 0x0c
234#define DSP_CAI_RATE_ADAPTATION_12000 0x0d
235#define DSP_CAI_RATE_ADAPTATION_1200_75 0x0e
236#define DSP_CAI_RATE_ADAPTATION_75_1200 0x0f
237#define DSP_CAI_RATE_ADAPTATION_MASK 0x0f
238#define DSP_CAI_ASYNC_PARITY_ENABLE 0x01
239#define DSP_CAI_ASYNC_PARITY_SPACE 0x00
240#define DSP_CAI_ASYNC_PARITY_ODD 0x02
241#define DSP_CAI_ASYNC_PARITY_EVEN 0x04
242#define DSP_CAI_ASYNC_PARITY_MARK 0x06
243#define DSP_CAI_ASYNC_PARITY_MASK 0x06
244#define DSP_CAI_ASYNC_ONE_STOP_BIT 0x00
245#define DSP_CAI_ASYNC_TWO_STOP_BITS 0x20
246#define DSP_CAI_ASYNC_CHAR_LENGTH_8 0x00
247#define DSP_CAI_ASYNC_CHAR_LENGTH_7 0x40
248#define DSP_CAI_ASYNC_CHAR_LENGTH_6 0x80
249#define DSP_CAI_ASYNC_CHAR_LENGTH_5 0xc0
250#define DSP_CAI_ASYNC_CHAR_LENGTH_MASK 0xc0
251#define DSP_CAI_MODEM_LEASED_LINE_MODE 0x01
252#define DSP_CAI_MODEM_4_WIRE_OPERATION 0x02
253#define DSP_CAI_MODEM_DISABLE_BUSY_DETECT 0x04
254#define DSP_CAI_MODEM_DISABLE_CALLING_TONE 0x08
255#define DSP_CAI_MODEM_DISABLE_ANSWER_TONE 0x10
256#define DSP_CAI_MODEM_ENABLE_DIAL_TONE_DET 0x20
257#define DSP_CAI_MODEM_USE_POTS_INTERFACE 0x40
258#define DSP_CAI_MODEM_FORCE_RAY_TAYLOR_FAX 0x80
259#define DSP_CAI_MODEM_NEGOTIATE_HIGHEST 0x00
260#define DSP_CAI_MODEM_NEGOTIATE_DISABLED 0x01
261#define DSP_CAI_MODEM_NEGOTIATE_IN_CLASS 0x02
262#define DSP_CAI_MODEM_NEGOTIATE_V100 0x03
263#define DSP_CAI_MODEM_NEGOTIATE_V8 0x04
264#define DSP_CAI_MODEM_NEGOTIATE_V8BIS 0x05
265#define DSP_CAI_MODEM_NEGOTIATE_MASK 0x07
266#define DSP_CAI_MODEM_GUARD_TONE_NONE 0x00
267#define DSP_CAI_MODEM_GUARD_TONE_550HZ 0x40
268#define DSP_CAI_MODEM_GUARD_TONE_1800HZ 0x80
269#define DSP_CAI_MODEM_GUARD_TONE_MASK 0xc0
270#define DSP_CAI_MODEM_DISABLE_RETRAIN 0x01
271#define DSP_CAI_MODEM_DISABLE_STEPUPDOWN 0x02
272#define DSP_CAI_MODEM_DISABLE_SPLIT_SPEED 0x04
273#define DSP_CAI_MODEM_DISABLE_TRELLIS 0x08
274#define DSP_CAI_MODEM_ALLOW_RDL_TEST_LOOP 0x10
275#define DSP_CAI_MODEM_DISABLE_FLUSH_TIMER 0x40
276#define DSP_CAI_MODEM_REVERSE_DIRECTION 0x80
277#define DSP_CAI_MODEM_DISABLE_V21 0x01
278#define DSP_CAI_MODEM_DISABLE_V23 0x02
279#define DSP_CAI_MODEM_DISABLE_V22 0x04
280#define DSP_CAI_MODEM_DISABLE_V22BIS 0x08
281#define DSP_CAI_MODEM_DISABLE_V32 0x10
282#define DSP_CAI_MODEM_DISABLE_V32BIS 0x20
283#define DSP_CAI_MODEM_DISABLE_V34 0x40
284#define DSP_CAI_MODEM_DISABLE_V90 0x80
285#define DSP_CAI_MODEM_DISABLE_BELL103 0x01
286#define DSP_CAI_MODEM_DISABLE_BELL212A 0x02
287#define DSP_CAI_MODEM_DISABLE_VFC 0x04
288#define DSP_CAI_MODEM_DISABLE_K56FLEX 0x08
289#define DSP_CAI_MODEM_DISABLE_X2 0x10
290#define DSP_CAI_MODEM_ENABLE_V29FDX 0x01
291#define DSP_CAI_MODEM_ENABLE_V33 0x02
292#define DSP_CAI_MODEM_DISABLE_2400_SYMBOLS 0x01
293#define DSP_CAI_MODEM_DISABLE_2743_SYMBOLS 0x02
294#define DSP_CAI_MODEM_DISABLE_2800_SYMBOLS 0x04
295#define DSP_CAI_MODEM_DISABLE_3000_SYMBOLS 0x08
296#define DSP_CAI_MODEM_DISABLE_3200_SYMBOLS 0x10
297#define DSP_CAI_MODEM_DISABLE_3429_SYMBOLS 0x20
298#define DSP_CAI_MODEM_DISABLE_TX_REDUCTION 0x01
299#define DSP_CAI_MODEM_DISABLE_PRECODING 0x02
300#define DSP_CAI_MODEM_DISABLE_PREEMPHASIS 0x04
301#define DSP_CAI_MODEM_DISABLE_SHAPING 0x08
302#define DSP_CAI_MODEM_DISABLE_NONLINEAR_EN 0x10
303#define DSP_CAI_MODEM_SPEAKER_OFF 0x00
304#define DSP_CAI_MODEM_SPEAKER_DURING_TRAIN 0x01
305#define DSP_CAI_MODEM_SPEAKER_TIL_CONNECT 0x02
306#define DSP_CAI_MODEM_SPEAKER_ALWAYS_ON 0x03
307#define DSP_CAI_MODEM_SPEAKER_CONTROL_MASK 0x03
308#define DSP_CAI_MODEM_SPEAKER_VOLUME_MIN 0x00
309#define DSP_CAI_MODEM_SPEAKER_VOLUME_LOW 0x04
310#define DSP_CAI_MODEM_SPEAKER_VOLUME_HIGH 0x08
311#define DSP_CAI_MODEM_SPEAKER_VOLUME_MAX 0x0c
312#define DSP_CAI_MODEM_SPEAKER_VOLUME_MASK 0x0c
313/* ==========================================================
314 DCD/CTS State
315 ========================================================== */
316#define MDM_WANT_CONNECT_B3_ACTIVE_I 0x01
317#define MDM_NCPI_VALID 0x02
318#define MDM_NCPI_CTS_ON_RECEIVED 0x04
319#define MDM_NCPI_DCD_ON_RECEIVED 0x08
320/* ==========================================================
321 CAPI NCPI Constants
322 ========================================================== */
323#define MDM_NCPI_ECM_V42 0x0001
324#define MDM_NCPI_ECM_MNP 0x0002
325#define MDM_NCPI_TRANSPARENT 0x0004
326#define MDM_NCPI_COMPRESSED 0x0010
327/* ==========================================================
328 CAPI B2 Config Constants
329 ========================================================== */
330#define MDM_B2_DISABLE_V42bis 0x0001
331#define MDM_B2_DISABLE_MNP 0x0002
332#define MDM_B2_DISABLE_TRANS 0x0004
333#define MDM_B2_DISABLE_V42 0x0008
334#define MDM_B2_DISABLE_COMP 0x0010
335/* ==========================================================
336 CAPI B1 Config Constants
337 ========================================================== */
338#define MDM_CAPI_DISABLE_RETRAIN 0x0001
339#define MDM_CAPI_DISABLE_RING_TONE 0x0002
340#define MDM_CAPI_GUARD_1800 0x0004
341#define MDM_CAPI_GUARD_550 0x0008
342#define MDM_CAPI_NEG_V8 0x0003
343#define MDM_CAPI_NEG_V100 0x0002
344#define MDM_CAPI_NEG_MOD_CLASS 0x0001
345#define MDM_CAPI_NEG_DISABLED 0x0000
346#endif
diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c
new file mode 100644
index 000000000000..f9b00f19afd2
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/message.c
@@ -0,0 +1,15047 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26
27
28
29
30
31#include "platform.h"
32#include "di_defs.h"
33#include "pc.h"
34#include "capi20.h"
35#include "divacapi.h"
36#include "mdm_msg.h"
37#include "divasync.h"
38
39
40
41#define FILE_ "MESSAGE.C"
42#define dprintf
43
44
45
46
47
48
49
50
51
52/*------------------------------------------------------------------*/
53/* This is options supported for all adapters that are server by */
54/* XDI driver. Allo it is not necessary to ask it from every adapter*/
55/* and it is not necessary to save it separate for every adapter */
56/* Macrose defined here have only local meaning */
57/*------------------------------------------------------------------*/
58static dword diva_xdi_extended_features = 0;
59
60#define DIVA_CAPI_USE_CMA 0x00000001
61#define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR 0x00000002
62#define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL 0x00000004
63#define DIVA_CAPI_XDI_PROVIDES_RX_DMA 0x00000008
64
65/*
66 CAPI can request to process all return codes self only if:
67 protocol code supports this && xdi supports this
68 */
69#define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__) (((__a__)->manufacturer_features&MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)&& ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) && (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
70
71/*------------------------------------------------------------------*/
72/* local function prototypes */
73/*------------------------------------------------------------------*/
74
75static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci);
76static void set_group_ind_mask (PLCI *plci);
77static void clear_group_ind_mask_bit (PLCI *plci, word b);
78static byte test_group_ind_mask_bit (PLCI *plci, word b);
79void AutomaticLaw(DIVA_CAPI_ADAPTER *);
80word CapiRelease(word);
81word CapiRegister(word);
82word api_put(APPL *, CAPI_MSG *);
83static word api_parse(byte *, word, byte *, API_PARSE *);
84static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
85static void api_load_msg(API_SAVE *in, API_PARSE *out);
86
87word api_remove_start(void);
88void api_remove_complete(void);
89
90static void plci_remove(PLCI *);
91static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a);
92static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
93
94void callback(ENTITY *);
95
96static void control_rc(PLCI *, byte, byte, byte, byte, byte);
97static void data_rc(PLCI *, byte);
98static void data_ack(PLCI *, byte);
99static void sig_ind(PLCI *);
100static void SendInfo(PLCI *, dword, byte * *, byte);
101static void SendSetupInfo(APPL *, PLCI *, dword, byte * *, byte);
102static void SendSSExtInd(APPL *, PLCI * plci, dword Id, byte * * parms);
103
104static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
105
106static void nl_ind(PLCI *);
107
108static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
116static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
117static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
118static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
119static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
120static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
121static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
122static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
123static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
124static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
125static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
126static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
127static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
128static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
129static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
130static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
131static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
132
133static word get_plci(DIVA_CAPI_ADAPTER *);
134static void add_p(PLCI *, byte, byte *);
135static void add_s(PLCI * plci, byte code, API_PARSE * p);
136static void add_ss(PLCI * plci, byte code, API_PARSE * p);
137static void add_ie(PLCI * plci, byte code, byte * p, word p_length);
138static void add_d(PLCI *, word, byte *);
139static void add_ai(PLCI *, API_PARSE *);
140static word add_b1(PLCI *, API_PARSE *, word, word);
141static word add_b23(PLCI *, API_PARSE *);
142static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms);
143static void sig_req(PLCI *, byte, byte);
144static void nl_req_ncci(PLCI *, byte, byte);
145static void send_req(PLCI *);
146static void send_data(PLCI *);
147static word plci_remove_check(PLCI *);
148static void listen_check(DIVA_CAPI_ADAPTER *);
149static byte AddInfo(byte **, byte **, byte *, byte *);
150static byte getChannel(API_PARSE *);
151static void IndParse(PLCI *, word *, byte **, byte);
152static byte ie_compare(byte *, byte *);
153static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
154static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER *,word);
155
156/*
157 XON protocol helpers
158 */
159static void channel_flow_control_remove (PLCI * plci);
160static void channel_x_off (PLCI * plci, byte ch, byte flag);
161static void channel_x_on (PLCI * plci, byte ch);
162static void channel_request_xon (PLCI * plci, byte ch);
163static void channel_xmit_xon (PLCI * plci);
164static int channel_can_xon (PLCI * plci, byte ch);
165static void channel_xmit_extended_xon (PLCI * plci);
166
167static byte SendMultiIE(PLCI * plci, dword Id, byte * * parms, byte ie_type, dword info_mask, byte setupParse);
168static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
169static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
170static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER * );
171static void VoiceChannelOff(PLCI *plci);
172static void adv_voice_write_coefs (PLCI *plci, word write_command);
173static void adv_voice_clear_config (PLCI *plci);
174
175static word get_b1_facilities (PLCI * plci, byte b1_resource);
176static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities);
177static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities);
178static word adjust_b_process (dword Id, PLCI *plci, byte Rc);
179static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
180static void adjust_b_restore (dword Id, PLCI *plci, byte Rc);
181static void reset_b3_command (dword Id, PLCI *plci, byte Rc);
182static void select_b_command (dword Id, PLCI *plci, byte Rc);
183static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc);
184static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc);
185static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc);
186static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc);
187static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc);
188static void hold_save_command (dword Id, PLCI *plci, byte Rc);
189static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc);
190static void init_b1_config (PLCI *plci);
191static void clear_b1_config (PLCI *plci);
192
193static void dtmf_command (dword Id, PLCI *plci, byte Rc);
194static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
195static void dtmf_confirmation (dword Id, PLCI *plci);
196static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length);
197static void dtmf_parameter_write (PLCI *plci);
198
199
200static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id);
201static void mixer_set_bchannel_id (PLCI *plci, byte *chi);
202static void mixer_clear_config (PLCI *plci);
203static void mixer_notify_update (PLCI *plci, byte others);
204static void mixer_command (dword Id, PLCI *plci, byte Rc);
205static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
206static void mixer_indication_coefs_set (dword Id, PLCI *plci);
207static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length);
208static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length);
209static void mixer_remove (PLCI *plci);
210
211
212static void ec_command (dword Id, PLCI *plci, byte Rc);
213static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
214static void ec_indication (dword Id, PLCI *plci, byte *msg, word length);
215
216
217static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc);
218static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc);
219
220
221static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic);
222static void diva_free_dma_descriptor (PLCI *plci, int nr);
223
224/*------------------------------------------------------------------*/
225/* external function prototypes */
226/*------------------------------------------------------------------*/
227
228extern byte MapController (byte);
229extern byte UnMapController (byte);
230#define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
231#define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
232
233void sendf(APPL *, word, dword, word, byte *, ...);
234void * TransmitBufferSet(APPL * appl, dword ref);
235void * TransmitBufferGet(APPL * appl, void * p);
236void TransmitBufferFree(APPL * appl, void * p);
237void * ReceiveBufferGet(APPL * appl, int Num);
238
239int fax_head_line_time (char *buffer);
240
241
242/*------------------------------------------------------------------*/
243/* Global data definitions */
244/*------------------------------------------------------------------*/
245extern byte max_adapter;
246extern byte max_appl;
247extern DIVA_CAPI_ADAPTER * adapter;
248extern APPL * application;
249
250
251
252
253
254
255
256static byte remove_started = FALSE;
257static PLCI dummy_plci;
258
259
260static struct _ftable {
261 word command;
262 byte * format;
263 byte (* function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
264} ftable[] = {
265 {_DATA_B3_R, "dwww", data_b3_req},
266 {_DATA_B3_I|RESPONSE, "w", data_b3_res},
267 {_INFO_R, "ss", info_req},
268 {_INFO_I|RESPONSE, "", info_res},
269 {_CONNECT_R, "wsssssssss", connect_req},
270 {_CONNECT_I|RESPONSE, "wsssss", connect_res},
271 {_CONNECT_ACTIVE_I|RESPONSE, "", connect_a_res},
272 {_DISCONNECT_R, "s", disconnect_req},
273 {_DISCONNECT_I|RESPONSE, "", disconnect_res},
274 {_LISTEN_R, "dddss", listen_req},
275 {_ALERT_R, "s", alert_req},
276 {_FACILITY_R, "ws", facility_req},
277 {_FACILITY_I|RESPONSE, "ws", facility_res},
278 {_CONNECT_B3_R, "s", connect_b3_req},
279 {_CONNECT_B3_I|RESPONSE, "ws", connect_b3_res},
280 {_CONNECT_B3_ACTIVE_I|RESPONSE, "", connect_b3_a_res},
281 {_DISCONNECT_B3_R, "s", disconnect_b3_req},
282 {_DISCONNECT_B3_I|RESPONSE, "", disconnect_b3_res},
283 {_RESET_B3_R, "s", reset_b3_req},
284 {_RESET_B3_I|RESPONSE, "", reset_b3_res},
285 {_CONNECT_B3_T90_ACTIVE_I|RESPONSE, "ws", connect_b3_t90_a_res},
286 {_CONNECT_B3_T90_ACTIVE_I|RESPONSE, "", connect_b3_t90_a_res},
287 {_SELECT_B_REQ, "s", select_b_req},
288 {_MANUFACTURER_R, "dws", manufacturer_req},
289 {_MANUFACTURER_I|RESPONSE, "dws", manufacturer_res},
290 {_MANUFACTURER_I|RESPONSE, "", manufacturer_res}
291};
292
293static byte * cip_bc[29][2] = {
294 { "", "" }, /* 0 */
295 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 1 */
296 { "\x02\x88\x90", "\x02\x88\x90" }, /* 2 */
297 { "\x02\x89\x90", "\x02\x89\x90" }, /* 3 */
298 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 4 */
299 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 5 */
300 { "\x02\x98\x90", "\x02\x98\x90" }, /* 6 */
301 { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
302 { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
303 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 9 */
304 { "", "" }, /* 10 */
305 { "", "" }, /* 11 */
306 { "", "" }, /* 12 */
307 { "", "" }, /* 13 */
308 { "", "" }, /* 14 */
309 { "", "" }, /* 15 */
310
311 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 16 */
312 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 17 */
313 { "\x02\x88\x90", "\x02\x88\x90" }, /* 18 */
314 { "\x02\x88\x90", "\x02\x88\x90" }, /* 19 */
315 { "\x02\x88\x90", "\x02\x88\x90" }, /* 20 */
316 { "\x02\x88\x90", "\x02\x88\x90" }, /* 21 */
317 { "\x02\x88\x90", "\x02\x88\x90" }, /* 22 */
318 { "\x02\x88\x90", "\x02\x88\x90" }, /* 23 */
319 { "\x02\x88\x90", "\x02\x88\x90" }, /* 24 */
320 { "\x02\x88\x90", "\x02\x88\x90" }, /* 25 */
321 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 26 */
322 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 27 */
323 { "\x02\x88\x90", "\x02\x88\x90" } /* 28 */
324};
325
326static byte * cip_hlc[29] = {
327 "", /* 0 */
328 "", /* 1 */
329 "", /* 2 */
330 "", /* 3 */
331 "", /* 4 */
332 "", /* 5 */
333 "", /* 6 */
334 "", /* 7 */
335 "", /* 8 */
336 "", /* 9 */
337 "", /* 10 */
338 "", /* 11 */
339 "", /* 12 */
340 "", /* 13 */
341 "", /* 14 */
342 "", /* 15 */
343
344 "\x02\x91\x81", /* 16 */
345 "\x02\x91\x84", /* 17 */
346 "\x02\x91\xa1", /* 18 */
347 "\x02\x91\xa4", /* 19 */
348 "\x02\x91\xa8", /* 20 */
349 "\x02\x91\xb1", /* 21 */
350 "\x02\x91\xb2", /* 22 */
351 "\x02\x91\xb5", /* 23 */
352 "\x02\x91\xb8", /* 24 */
353 "\x02\x91\xc1", /* 25 */
354 "\x02\x91\x81", /* 26 */
355 "\x03\x91\xe0\x01", /* 27 */
356 "\x03\x91\xe0\x02" /* 28 */
357};
358
359/*------------------------------------------------------------------*/
360
361#define V120_HEADER_LENGTH 1
362#define V120_HEADER_EXTEND_BIT 0x80
363#define V120_HEADER_BREAK_BIT 0x40
364#define V120_HEADER_C1_BIT 0x04
365#define V120_HEADER_C2_BIT 0x08
366#define V120_HEADER_FLUSH_COND (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
367
368static byte v120_default_header[] =
369{
370
371 0x83 /* Ext, BR , res, res, C2 , C1 , B , F */
372
373};
374
375static byte v120_break_header[] =
376{
377
378 0xc3 | V120_HEADER_BREAK_BIT /* Ext, BR , res, res, C2 , C1 , B , F */
379
380};
381
382
383/*------------------------------------------------------------------*/
384/* API_PUT function */
385/*------------------------------------------------------------------*/
386
387word api_put(APPL * appl, CAPI_MSG * msg)
388{
389 word i, j, k, l, n;
390 word ret;
391 byte c;
392 byte controller;
393 DIVA_CAPI_ADAPTER * a;
394 PLCI * plci;
395 NCCI * ncci_ptr;
396 word ncci;
397 CAPI_MSG *m;
398 API_PARSE msg_parms[MAX_MSG_PARMS+1];
399
400 if (msg->header.length < sizeof (msg->header) ||
401 msg->header.length > MAX_MSG_SIZE) {
402 dbug(1,dprintf("bad len"));
403 return _BAD_MSG;
404 }
405
406 controller = (byte)((msg->header.controller &0x7f)-1);
407
408 /* controller starts with 0 up to (max_adapter - 1) */
409 if ( controller >= max_adapter )
410 {
411 dbug(1,dprintf("invalid ctrl"));
412 return _BAD_MSG;
413 }
414
415 a = &adapter[controller];
416 plci = NULL;
417 if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
418 {
419 dbug(1,dprintf("plci=%x",msg->header.plci));
420 plci = &a->plci[msg->header.plci-1];
421 ncci = GET_WORD(&msg->header.ncci);
422 if (plci->Id
423 && (plci->appl
424 || (plci->State == INC_CON_PENDING)
425 || (plci->State == INC_CON_ALERT)
426 || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
427 && ((ncci == 0)
428 || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
429 || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
430 {
431 i = plci->msg_in_read_pos;
432 j = plci->msg_in_write_pos;
433 if (j >= i)
434 {
435 if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
436 i += MSG_IN_QUEUE_SIZE - j;
437 else
438 j = 0;
439 }
440 else
441 {
442
443 n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
444
445 if (i > MSG_IN_QUEUE_SIZE - n)
446 i = MSG_IN_QUEUE_SIZE - n + 1;
447 i -= j;
448 }
449
450 if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
451
452 {
453 dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
454 msg->header.length, plci->msg_in_write_pos,
455 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
456
457 return _QUEUE_FULL;
458 }
459 c = FALSE;
460 if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
461 || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
462 {
463 if (plci->msg_in_write_pos != plci->msg_in_read_pos)
464 c = TRUE;
465 }
466 if (msg->header.command == _DATA_B3_R)
467 {
468 if (msg->header.length < 20)
469 {
470 dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
471 return _BAD_MSG;
472 }
473 ncci_ptr = &(a->ncci[ncci]);
474 n = ncci_ptr->data_pending;
475 l = ncci_ptr->data_ack_pending;
476 k = plci->msg_in_read_pos;
477 while (k != plci->msg_in_write_pos)
478 {
479 if (k == plci->msg_in_wrap_pos)
480 k = 0;
481 if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
482 && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
483 {
484 n++;
485 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
486 l++;
487 }
488
489 k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
490 MSG_IN_OVERHEAD + 3) & 0xfffc;
491
492 }
493 if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
494 {
495 dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
496 ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
497
498 return _QUEUE_FULL;
499 }
500 if (plci->req_in || plci->internal_command)
501 {
502 if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
503 && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
504 {
505 dbug(0,dprintf("Q-FULL3(requeue)"));
506
507 return _QUEUE_FULL;
508 }
509 c = TRUE;
510 }
511 }
512 else
513 {
514 if (plci->req_in || plci->internal_command)
515 c = TRUE;
516 else
517 {
518 plci->command = msg->header.command;
519 plci->number = msg->header.number;
520 }
521 }
522 if (c)
523 {
524 dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
525 msg->header.command, plci->req_in, plci->internal_command,
526 msg->header.length, plci->msg_in_write_pos,
527 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
528 if (j == 0)
529 plci->msg_in_wrap_pos = plci->msg_in_write_pos;
530 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
531 for (i = 0; i < msg->header.length; i++)
532 ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
533 if (m->header.command == _DATA_B3_R)
534 {
535
536 m->info.data_b3_req.Data = (dword)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
537
538 }
539
540 j = (j + 3) & 0xfffc;
541
542 *((APPL * *)(&((byte *)(plci->msg_in_queue))[j])) = appl;
543 plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
544 return 0;
545 }
546 }
547 else
548 {
549 plci = NULL;
550 }
551 }
552 dbug(1,dprintf("com=%x",msg->header.command));
553
554 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
555 for(i=0, ret = _BAD_MSG;
556 i<(sizeof(ftable)/sizeof(struct _ftable));
557 i++) {
558
559 if(ftable[i].command==msg->header.command) {
560 /* break loop if the message is correct, otherwise continue scan */
561 /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */
562 if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
563 ret = 0;
564 break;
565 }
566 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
567 }
568 }
569 if(ret) {
570 dbug(1,dprintf("BAD_MSG"));
571 if(plci) plci->command = 0;
572 return ret;
573 }
574
575
576 c = ftable[i].function(GET_DWORD(&msg->header.controller),
577 msg->header.number,
578 a,
579 plci,
580 appl,
581 msg_parms);
582
583 channel_xmit_extended_xon (plci);
584
585 if(c==1) send_req(plci);
586 if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
587 if(plci && !plci->req_in) plci->command = 0;
588 return 0;
589}
590
591
592/*------------------------------------------------------------------*/
593/* api_parse function, check the format of api messages */
594/*------------------------------------------------------------------*/
595
596word api_parse(byte * msg, word length, byte * format, API_PARSE * parms)
597{
598 word i;
599 word p;
600
601 for(i=0,p=0; format[i]; i++) {
602 if(parms)
603 {
604 parms[i].info = &msg[p];
605 }
606 switch(format[i]) {
607 case 'b':
608 p +=1;
609 break;
610 case 'w':
611 p +=2;
612 break;
613 case 'd':
614 p +=4;
615 break;
616 case 's':
617 if(msg[p]==0xff) {
618 parms[i].info +=2;
619 parms[i].length = msg[p+1] + (msg[p+2]<<8);
620 p +=(parms[i].length +3);
621 }
622 else {
623 parms[i].length = msg[p];
624 p +=(parms[i].length +1);
625 }
626 break;
627 }
628
629 if(p>length) return TRUE;
630 }
631 if(parms) parms[i].info = NULL;
632 return FALSE;
633}
634
635void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
636{
637 word i, j, n = 0;
638 byte *p;
639
640 p = out->info;
641 for (i = 0; format[i] != '\0'; i++)
642 {
643 out->parms[i].info = p;
644 out->parms[i].length = in[i].length;
645 switch (format[i])
646 {
647 case 'b':
648 n = 1;
649 break;
650 case 'w':
651 n = 2;
652 break;
653 case 'd':
654 n = 4;
655 break;
656 case 's':
657 n = in[i].length + 1;
658 break;
659 }
660 for (j = 0; j < n; j++)
661 *(p++) = in[i].info[j];
662 }
663 out->parms[i].info = NULL;
664 out->parms[i].length = 0;
665}
666
667void api_load_msg(API_SAVE *in, API_PARSE *out)
668{
669 word i;
670
671 i = 0;
672 do
673 {
674 out[i].info = in->parms[i].info;
675 out[i].length = in->parms[i].length;
676 } while (in->parms[i++].info);
677}
678
679
680/*------------------------------------------------------------------*/
681/* CAPI remove function */
682/*------------------------------------------------------------------*/
683
684word api_remove_start(void)
685{
686 word i;
687 word j;
688
689 if(!remove_started) {
690 remove_started = TRUE;
691 for(i=0;i<max_adapter;i++) {
692 if(adapter[i].request) {
693 for(j=0;j<adapter[i].max_plci;j++) {
694 if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
695 }
696 }
697 }
698 return 1;
699 }
700 else {
701 for(i=0;i<max_adapter;i++) {
702 if(adapter[i].request) {
703 for(j=0;j<adapter[i].max_plci;j++) {
704 if(adapter[i].plci[j].Sig.Id) return 1;
705 }
706 }
707 }
708 }
709 api_remove_complete();
710 return 0;
711}
712
713
714/*------------------------------------------------------------------*/
715/* internal command queue */
716/*------------------------------------------------------------------*/
717
718static void init_internal_command_queue (PLCI *plci)
719{
720 word i;
721
722 dbug (1, dprintf ("%s,%d: init_internal_command_queue",
723 (char *)(FILE_), __LINE__));
724
725 plci->internal_command = 0;
726 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
727 plci->internal_command_queue[i] = NULL;
728}
729
730
731static void start_internal_command (dword Id, PLCI *plci, t_std_internal_command command_function)
732{
733 word i;
734
735 dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
736 UnMapId (Id), (char *)(FILE_), __LINE__));
737
738 if (plci->internal_command == 0)
739 {
740 plci->internal_command_queue[0] = command_function;
741 (* command_function)(Id, plci, OK);
742 }
743 else
744 {
745 i = 1;
746 while (plci->internal_command_queue[i] != 0)
747 i++;
748 plci->internal_command_queue[i] = command_function;
749 }
750}
751
752
753static void next_internal_command (dword Id, PLCI *plci)
754{
755 word i;
756
757 dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
758 UnMapId (Id), (char *)(FILE_), __LINE__));
759
760 plci->internal_command = 0;
761 plci->internal_command_queue[0] = NULL;
762 while (plci->internal_command_queue[1] != 0)
763 {
764 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
765 plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
766 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
767 (*(plci->internal_command_queue[0]))(Id, plci, OK);
768 if (plci->internal_command != 0)
769 return;
770 plci->internal_command_queue[0] = NULL;
771 }
772}
773
774
775/*------------------------------------------------------------------*/
776/* NCCI allocate/remove function */
777/*------------------------------------------------------------------*/
778
779static dword ncci_mapping_bug = 0;
780
781static word get_ncci (PLCI *plci, byte ch, word force_ncci)
782{
783 DIVA_CAPI_ADAPTER *a;
784 word ncci, i, j, k;
785
786 a = plci->adapter;
787 if (!ch || a->ch_ncci[ch])
788 {
789 ncci_mapping_bug++;
790 dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
791 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
792 ncci = ch;
793 }
794 else
795 {
796 if (force_ncci)
797 ncci = force_ncci;
798 else
799 {
800 if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
801 ncci = ch;
802 else
803 {
804 ncci = 1;
805 while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
806 ncci++;
807 if (ncci == MAX_NCCI+1)
808 {
809 ncci_mapping_bug++;
810 i = 1;
811 do
812 {
813 j = 1;
814 while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
815 j++;
816 k = j;
817 if (j < MAX_NCCI+1)
818 {
819 do
820 {
821 j++;
822 } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
823 }
824 } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
825 if (i < MAX_NL_CHANNEL+1)
826 {
827 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
828 ncci_mapping_bug, ch, force_ncci, i, k, j));
829 }
830 else
831 {
832 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
833 ncci_mapping_bug, ch, force_ncci));
834 }
835 ncci = ch;
836 }
837 }
838 a->ncci_plci[ncci] = plci->Id;
839 a->ncci_state[ncci] = IDLE;
840 if (!plci->ncci_ring_list)
841 plci->ncci_ring_list = ncci;
842 else
843 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
844 a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
845 }
846 a->ncci_ch[ncci] = ch;
847 a->ch_ncci[ch] = (byte) ncci;
848 dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
849 ncci_mapping_bug, ch, force_ncci, ch, ncci));
850 }
851 return (ncci);
852}
853
854
855static void ncci_free_receive_buffers (PLCI *plci, word ncci)
856{
857 DIVA_CAPI_ADAPTER *a;
858 APPL *appl;
859 word i, ncci_code;
860 dword Id;
861
862 a = plci->adapter;
863 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
864 if (ncci)
865 {
866 if (a->ncci_plci[ncci] == plci->Id)
867 {
868 if (!plci->appl)
869 {
870 ncci_mapping_bug++;
871 dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
872 ncci_mapping_bug, Id));
873 }
874 else
875 {
876 appl = plci->appl;
877 ncci_code = ncci | (((word) a->Id) << 8);
878 for (i = 0; i < appl->MaxBuffer; i++)
879 {
880 if ((appl->DataNCCI[i] == ncci_code)
881 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
882 {
883 appl->DataNCCI[i] = 0;
884 }
885 }
886 }
887 }
888 }
889 else
890 {
891 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
892 {
893 if (a->ncci_plci[ncci] == plci->Id)
894 {
895 if (!plci->appl)
896 {
897 ncci_mapping_bug++;
898 dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
899 ncci_mapping_bug, Id));
900 }
901 else
902 {
903 appl = plci->appl;
904 ncci_code = ncci | (((word) a->Id) << 8);
905 for (i = 0; i < appl->MaxBuffer; i++)
906 {
907 if ((appl->DataNCCI[i] == ncci_code)
908 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
909 {
910 appl->DataNCCI[i] = 0;
911 }
912 }
913 }
914 }
915 }
916 }
917}
918
919
920static void cleanup_ncci_data (PLCI *plci, word ncci)
921{
922 NCCI *ncci_ptr;
923
924 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
925 {
926 ncci_ptr = &(plci->adapter->ncci[ncci]);
927 if (plci->appl)
928 {
929 while (ncci_ptr->data_pending != 0)
930 {
931 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
932 TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
933 (ncci_ptr->data_out)++;
934 if (ncci_ptr->data_out == MAX_DATA_B3)
935 ncci_ptr->data_out = 0;
936 (ncci_ptr->data_pending)--;
937 }
938 }
939 ncci_ptr->data_out = 0;
940 ncci_ptr->data_pending = 0;
941 ncci_ptr->data_ack_out = 0;
942 ncci_ptr->data_ack_pending = 0;
943 }
944}
945
946
947static void ncci_remove (PLCI *plci, word ncci, byte preserve_ncci)
948{
949 DIVA_CAPI_ADAPTER *a;
950 dword Id;
951 word i;
952
953 a = plci->adapter;
954 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
955 if (!preserve_ncci)
956 ncci_free_receive_buffers (plci, ncci);
957 if (ncci)
958 {
959 if (a->ncci_plci[ncci] != plci->Id)
960 {
961 ncci_mapping_bug++;
962 dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
963 ncci_mapping_bug, Id, preserve_ncci));
964 }
965 else
966 {
967 cleanup_ncci_data (plci, ncci);
968 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
969 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
970 a->ch_ncci[a->ncci_ch[ncci]] = 0;
971 if (!preserve_ncci)
972 {
973 a->ncci_ch[ncci] = 0;
974 a->ncci_plci[ncci] = 0;
975 a->ncci_state[ncci] = IDLE;
976 i = plci->ncci_ring_list;
977 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
978 i = a->ncci_next[i];
979 if ((i != 0) && (a->ncci_next[i] == ncci))
980 {
981 if (i == ncci)
982 plci->ncci_ring_list = 0;
983 else if (plci->ncci_ring_list == ncci)
984 plci->ncci_ring_list = i;
985 a->ncci_next[i] = a->ncci_next[ncci];
986 }
987 a->ncci_next[ncci] = 0;
988 }
989 }
990 }
991 else
992 {
993 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
994 {
995 if (a->ncci_plci[ncci] == plci->Id)
996 {
997 cleanup_ncci_data (plci, ncci);
998 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
999 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
1000 a->ch_ncci[a->ncci_ch[ncci]] = 0;
1001 if (!preserve_ncci)
1002 {
1003 a->ncci_ch[ncci] = 0;
1004 a->ncci_plci[ncci] = 0;
1005 a->ncci_state[ncci] = IDLE;
1006 a->ncci_next[ncci] = 0;
1007 }
1008 }
1009 }
1010 if (!preserve_ncci)
1011 plci->ncci_ring_list = 0;
1012 }
1013}
1014
1015
1016/*------------------------------------------------------------------*/
1017/* PLCI remove function */
1018/*------------------------------------------------------------------*/
1019
1020static void plci_free_msg_in_queue (PLCI *plci)
1021{
1022 word i;
1023
1024 if (plci->appl)
1025 {
1026 i = plci->msg_in_read_pos;
1027 while (i != plci->msg_in_write_pos)
1028 {
1029 if (i == plci->msg_in_wrap_pos)
1030 i = 0;
1031 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1032 {
1033
1034 TransmitBufferFree (plci->appl,
1035 (byte *)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1036
1037 }
1038
1039 i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1040 MSG_IN_OVERHEAD + 3) & 0xfffc;
1041
1042 }
1043 }
1044 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1045 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1046 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1047}
1048
1049
1050static void plci_remove(PLCI * plci)
1051{
1052
1053 if(!plci) {
1054 dbug(1,dprintf("plci_remove(no plci)"));
1055 return;
1056 }
1057 init_internal_command_queue (plci);
1058 dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1059 if(plci_remove_check(plci))
1060 {
1061 return;
1062 }
1063 if (plci->Sig.Id == 0xff)
1064 {
1065 dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1066 if (plci->NL.Id && !plci->nl_remove_id)
1067 {
1068 nl_req_ncci(plci,REMOVE,0);
1069 send_req(plci);
1070 }
1071 }
1072 else
1073 {
1074 if (!plci->sig_remove_id
1075 && (plci->Sig.Id
1076 || (plci->req_in!=plci->req_out)
1077 || (plci->nl_req || plci->sig_req)))
1078 {
1079 sig_req(plci,HANGUP,0);
1080 send_req(plci);
1081 }
1082 }
1083 ncci_remove (plci, 0, FALSE);
1084 plci_free_msg_in_queue (plci);
1085
1086 plci->channels = 0;
1087 plci->appl = NULL;
1088 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1089 plci->State = OUTG_DIS_PENDING;
1090}
1091
1092/*------------------------------------------------------------------*/
1093/* Application Group function helpers */
1094/*------------------------------------------------------------------*/
1095
1096static void set_group_ind_mask (PLCI *plci)
1097{
1098 word i;
1099
1100 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1101 plci->group_optimization_mask_table[i] = 0xffffffffL;
1102}
1103
1104static void clear_group_ind_mask_bit (PLCI *plci, word b)
1105{
1106 plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1107}
1108
1109static byte test_group_ind_mask_bit (PLCI *plci, word b)
1110{
1111 return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1112}
1113
1114/*------------------------------------------------------------------*/
1115/* c_ind_mask operations for arbitrary MAX_APPL */
1116/*------------------------------------------------------------------*/
1117
1118static void clear_c_ind_mask (PLCI *plci)
1119{
1120 word i;
1121
1122 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1123 plci->c_ind_mask_table[i] = 0;
1124}
1125
1126static byte c_ind_mask_empty (PLCI *plci)
1127{
1128 word i;
1129
1130 i = 0;
1131 while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1132 i++;
1133 return (i == C_IND_MASK_DWORDS);
1134}
1135
1136static void set_c_ind_mask_bit (PLCI *plci, word b)
1137{
1138 plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1139}
1140
1141static void clear_c_ind_mask_bit (PLCI *plci, word b)
1142{
1143 plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1144}
1145
1146static byte test_c_ind_mask_bit (PLCI *plci, word b)
1147{
1148 return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1149}
1150
1151static void dump_c_ind_mask (PLCI *plci)
1152{
1153static char hex_digit_table[0x10] =
1154 {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1155 word i, j, k;
1156 dword d;
1157 char *p;
1158 char buf[40];
1159
1160 for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1161 {
1162 p = buf + 36;
1163 *p = '\0';
1164 for (j = 0; j < 4; j++)
1165 {
1166 if (i+j < C_IND_MASK_DWORDS)
1167 {
1168 d = plci->c_ind_mask_table[i+j];
1169 for (k = 0; k < 8; k++)
1170 {
1171 *(--p) = hex_digit_table[d & 0xf];
1172 d >>= 4;
1173 }
1174 }
1175 else if (i != 0)
1176 {
1177 for (k = 0; k < 8; k++)
1178 *(--p) = ' ';
1179 }
1180 *(--p) = ' ';
1181 }
1182 dbug(1,dprintf ("c_ind_mask =%s", (char *) p));
1183 }
1184}
1185
1186
1187
1188
1189
1190#define dump_plcis(a)
1191
1192
1193
1194/*------------------------------------------------------------------*/
1195/* translation function for each message */
1196/*------------------------------------------------------------------*/
1197
1198byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1199{
1200 word ch;
1201 word i;
1202 word Info;
1203 word CIP;
1204 byte LinkLayer;
1205 API_PARSE * ai;
1206 API_PARSE * bp;
1207 API_PARSE ai_parms[5];
1208 word channel = 0;
1209 dword ch_mask;
1210 byte m;
1211 static byte esc_chi[35] = {0x02,0x18,0x01};
1212 static byte lli[2] = {0x01,0x00};
1213 byte noCh = 0;
1214 word dir = 0;
1215 byte *p_chi = "";
1216
1217 for(i=0;i<5;i++) ai_parms[i].length = 0;
1218
1219 dbug(1,dprintf("connect_req(%d)",parms->length));
1220 Info = _WRONG_IDENTIFIER;
1221 if(a)
1222 {
1223 if(a->adapter_disabled)
1224 {
1225 dbug(1,dprintf("adapter disabled"));
1226 Id = ((word)1<<8)|a->Id;
1227 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1228 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1229 return FALSE;
1230 }
1231 Info = _OUT_OF_PLCI;
1232 if((i=get_plci(a)))
1233 {
1234 Info = 0;
1235 plci = &a->plci[i-1];
1236 plci->appl = appl;
1237 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1238 /* check 'external controller' bit for codec support */
1239 if(Id & EXT_CONTROLLER)
1240 {
1241 if(AdvCodecSupport(a, plci, appl, 0) )
1242 {
1243 plci->Id = 0;
1244 sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1245 return 2;
1246 }
1247 }
1248 ai = &parms[9];
1249 bp = &parms[5];
1250 ch = 0;
1251 if(bp->length)LinkLayer = bp->info[3];
1252 else LinkLayer = 0;
1253 if(ai->length)
1254 {
1255 ch=0xffff;
1256 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1257 {
1258 ch = 0;
1259 if(ai_parms[0].length)
1260 {
1261 ch = GET_WORD(ai_parms[0].info+1);
1262 if(ch>4) ch=0; /* safety -> ignore ChannelID */
1263 if(ch==4) /* explizit CHI in message */
1264 {
1265 /* check length of B-CH struct */
1266 if((ai_parms[0].info)[3]>=1)
1267 {
1268 if((ai_parms[0].info)[4]==CHI)
1269 {
1270 p_chi = &((ai_parms[0].info)[5]);
1271 }
1272 else
1273 {
1274 p_chi = &((ai_parms[0].info)[3]);
1275 }
1276 if(p_chi[0]>35) /* check length of channel ID */
1277 {
1278 Info = _WRONG_MESSAGE_FORMAT;
1279 }
1280 }
1281 else Info = _WRONG_MESSAGE_FORMAT;
1282 }
1283
1284 if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1285 {
1286 dir = GET_WORD(ai_parms[0].info+3);
1287 ch_mask = 0;
1288 m = 0x3f;
1289 for(i=0; i+5<=ai_parms[0].length; i++)
1290 {
1291 if(ai_parms[0].info[i+5]!=0)
1292 {
1293 if((ai_parms[0].info[i+5] | m) != 0xff)
1294 Info = _WRONG_MESSAGE_FORMAT;
1295 else
1296 {
1297 if (ch_mask == 0)
1298 channel = i;
1299 ch_mask |= 1L << i;
1300 }
1301 }
1302 m = 0;
1303 }
1304 if (ch_mask == 0)
1305 Info = _WRONG_MESSAGE_FORMAT;
1306 if (!Info)
1307 {
1308 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1309 {
1310 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1311 for(i=0; i+5<=ai_parms[0].length; i++)
1312 esc_chi[i+3] = ai_parms[0].info[i+5];
1313 }
1314 else
1315 esc_chi[0] = 2;
1316 esc_chi[2] = (byte)channel;
1317 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1318 add_p(plci,LLI,lli);
1319 add_p(plci,ESC,esc_chi);
1320 plci->State = LOCAL_CONNECT;
1321 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1322 }
1323 }
1324 }
1325 }
1326 else Info = _WRONG_MESSAGE_FORMAT;
1327 }
1328
1329 dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1330 plci->command = _CONNECT_R;
1331 plci->number = Number;
1332 /* x.31 or D-ch free SAPI in LinkLayer? */
1333 if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = TRUE;
1334 if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1335 {
1336 /* B-channel used for B3 connections (ch==0), or no B channel */
1337 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1338 if(noCh) Info = add_b1(plci,&parms[5],2,0); /* no resource */
1339 else Info = add_b1(plci,&parms[5],ch,0);
1340 add_s(plci,OAD,&parms[2]);
1341 add_s(plci,OSA,&parms[4]);
1342 add_s(plci,BC,&parms[6]);
1343 add_s(plci,LLC,&parms[7]);
1344 add_s(plci,HLC,&parms[8]);
1345 CIP = GET_WORD(parms[0].info);
1346 if (a->Info_Mask[appl->Id-1] & 0x200)
1347 {
1348 /* early B3 connect (CIP mask bit 9) no release after a disc */
1349 add_p(plci,LLI,"\x01\x01");
1350 }
1351 if(GET_WORD(parms[0].info)<29) {
1352 add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1353 add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1354 }
1355 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1356 sig_req(plci,ASSIGN,DSIG_ID);
1357 }
1358 else if(ch==1) {
1359
1360 /* D-Channel used for B3 connections */
1361 plci->Sig.Id = 0xff;
1362 Info = 0;
1363 }
1364
1365 if(!Info && ch!=2 && !noCh ) {
1366 Info = add_b23(plci,&parms[5]);
1367 if(!Info) {
1368 if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1369 }
1370 }
1371
1372 if(!Info)
1373 {
1374 if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1375 {
1376 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1377 {
1378 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1379 plci->spoofed_msg = CALL_REQ;
1380 plci->internal_command = BLOCK_PLCI;
1381 plci->command = 0;
1382 dbug(1,dprintf("Spoof"));
1383 send_req(plci);
1384 return FALSE;
1385 }
1386 if(ch==4)add_p(plci,CHI,p_chi);
1387 add_s(plci,CPN,&parms[1]);
1388 add_s(plci,DSA,&parms[3]);
1389 if(noCh) add_p(plci,ESC,"\x02\x18\xfd"); /* D-channel, no B-L3 */
1390 add_ai(plci,&parms[9]);
1391 if(!dir)sig_req(plci,CALL_REQ,0);
1392 else
1393 {
1394 plci->command = PERM_LIST_REQ;
1395 plci->appl = appl;
1396 sig_req(plci,LISTEN_REQ,0);
1397 send_req(plci);
1398 return FALSE;
1399 }
1400 }
1401 send_req(plci);
1402 return FALSE;
1403 }
1404 plci->Id = 0;
1405 }
1406 }
1407 sendf(appl,
1408 _CONNECT_R|CONFIRM,
1409 Id,
1410 Number,
1411 "w",Info);
1412 return 2;
1413}
1414
1415byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1416{
1417 word i, Info;
1418 word Reject;
1419 static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1420 static byte esc_t[] = {0x03,0x08,0x00,0x00};
1421 API_PARSE * ai;
1422 API_PARSE ai_parms[5];
1423 word ch=0;
1424
1425 if(!plci) {
1426 dbug(1,dprintf("connect_res(no plci)"));
1427 return 0; /* no plci, no send */
1428 }
1429
1430 dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1431 for(i=0;i<5;i++) ai_parms[i].length = 0;
1432 ai = &parms[5];
1433 dbug(1,dprintf("ai->length=%d",ai->length));
1434
1435 if(ai->length)
1436 {
1437 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1438 {
1439 dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1440 ch = 0;
1441 if(ai_parms[0].length)
1442 {
1443 ch = GET_WORD(ai_parms[0].info+1);
1444 dbug(1,dprintf("BCH-I=0x%x",ch));
1445 }
1446 }
1447 }
1448
1449 if(plci->State==INC_CON_CONNECTED_ALERT)
1450 {
1451 dbug(1,dprintf("Connected Alert Call_Res"));
1452 if (a->Info_Mask[appl->Id-1] & 0x200)
1453 {
1454 /* early B3 connect (CIP mask bit 9) no release after a disc */
1455 add_p(plci,LLI,"\x01\x01");
1456 }
1457 add_s(plci, CONN_NR, &parms[2]);
1458 add_s(plci, LLC, &parms[4]);
1459 add_ai(plci, &parms[5]);
1460 plci->State = INC_CON_ACCEPT;
1461 sig_req(plci, CALL_RES,0);
1462 return 1;
1463 }
1464 else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1465 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1466 dump_c_ind_mask (plci);
1467 Reject = GET_WORD(parms[0].info);
1468 dbug(1,dprintf("Reject=0x%x",Reject));
1469 if(Reject)
1470 {
1471 if(c_ind_mask_empty (plci))
1472 {
1473 if((Reject&0xff00)==0x3400)
1474 {
1475 esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1476 add_p(plci,ESC,esc_t);
1477 add_ai(plci, &parms[5]);
1478 sig_req(plci,REJECT,0);
1479 }
1480 else if(Reject==1 || Reject>9)
1481 {
1482 add_ai(plci, &parms[5]);
1483 sig_req(plci,HANGUP,0);
1484 }
1485 else
1486 {
1487 esc_t[2] = cau_t[(Reject&0x000f)];
1488 add_p(plci,ESC,esc_t);
1489 add_ai(plci, &parms[5]);
1490 sig_req(plci,REJECT,0);
1491 }
1492 plci->appl = appl;
1493 }
1494 else
1495 {
1496 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1497 }
1498 }
1499 else {
1500 plci->appl = appl;
1501 if(Id & EXT_CONTROLLER){
1502 if(AdvCodecSupport(a, plci, appl, 0)){
1503 dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1504 sig_req(plci,HANGUP,0);
1505 return 1;
1506 }
1507 if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1508 {
1509 Info = add_b23(plci, &parms[1]);
1510 if (Info)
1511 {
1512 dbug(1,dprintf("connect_res(error from add_b23)"));
1513 sig_req(plci,HANGUP,0);
1514 return 1;
1515 }
1516 if(plci->adv_nl)
1517 {
1518 nl_req_ncci(plci, ASSIGN, 0);
1519 }
1520 }
1521 }
1522 else
1523 {
1524 plci->tel = 0;
1525 if(ch!=2)
1526 {
1527 Info = add_b23(plci, &parms[1]);
1528 if (Info)
1529 {
1530 dbug(1,dprintf("connect_res(error from add_b23 2)"));
1531 sig_req(plci,HANGUP,0);
1532 return 1;
1533 }
1534 }
1535 nl_req_ncci(plci, ASSIGN, 0);
1536 }
1537
1538 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1539 {
1540 api_save_msg(parms, "wsssss", &plci->saved_msg);
1541 plci->spoofed_msg = CALL_RES;
1542 plci->internal_command = BLOCK_PLCI;
1543 plci->command = 0;
1544 dbug(1,dprintf("Spoof"));
1545 }
1546 else
1547 {
1548 add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1549 if (a->Info_Mask[appl->Id-1] & 0x200)
1550 {
1551 /* early B3 connect (CIP mask bit 9) no release after a disc */
1552 add_p(plci,LLI,"\x01\x01");
1553 }
1554 add_s(plci, CONN_NR, &parms[2]);
1555 add_s(plci, LLC, &parms[4]);
1556 add_ai(plci, &parms[5]);
1557 plci->State = INC_CON_ACCEPT;
1558 sig_req(plci, CALL_RES,0);
1559 }
1560
1561 for(i=0; i<max_appl; i++) {
1562 if(test_c_ind_mask_bit (plci, i)) {
1563 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1564 }
1565 }
1566 }
1567 }
1568 return 1;
1569}
1570
1571byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1572{
1573 dbug(1,dprintf("connect_a_res"));
1574 return FALSE;
1575}
1576
1577byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1578{
1579 word Info;
1580 word i;
1581
1582 dbug(1,dprintf("disconnect_req"));
1583
1584 Info = _WRONG_IDENTIFIER;
1585
1586 if(plci)
1587 {
1588 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1589 {
1590 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1591 plci->appl = appl;
1592 for(i=0; i<max_appl; i++)
1593 {
1594 if(test_c_ind_mask_bit (plci, i))
1595 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1596 }
1597 plci->State = OUTG_DIS_PENDING;
1598 }
1599 if(plci->Sig.Id && plci->appl)
1600 {
1601 Info = 0;
1602 if(plci->Sig.Id!=0xff)
1603 {
1604 if(plci->State!=INC_DIS_PENDING)
1605 {
1606 add_ai(plci, &msg[0]);
1607 sig_req(plci,HANGUP,0);
1608 plci->State = OUTG_DIS_PENDING;
1609 return 1;
1610 }
1611 }
1612 else
1613 {
1614 if (plci->NL.Id && !plci->nl_remove_id)
1615 {
1616 mixer_remove (plci);
1617 nl_req_ncci(plci,REMOVE,0);
1618 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1619 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1620 plci->State = INC_DIS_PENDING;
1621 }
1622 return 1;
1623 }
1624 }
1625 }
1626
1627 if(!appl) return FALSE;
1628 sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1629 return FALSE;
1630}
1631
1632byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1633{
1634 dbug(1,dprintf("disconnect_res"));
1635 if(plci)
1636 {
1637 /* clear ind mask bit, just in case of collsion of */
1638 /* DISCONNECT_IND and CONNECT_RES */
1639 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1640 ncci_free_receive_buffers (plci, 0);
1641 if(plci_remove_check(plci))
1642 {
1643 return 0;
1644 }
1645 if(plci->State==INC_DIS_PENDING
1646 || plci->State==SUSPENDING) {
1647 if(c_ind_mask_empty (plci)) {
1648 if(plci->State!=SUSPENDING)plci->State = IDLE;
1649 dbug(1,dprintf("chs=%d",plci->channels));
1650 if(!plci->channels) {
1651 plci_remove(plci);
1652 }
1653 }
1654 }
1655 }
1656 return 0;
1657}
1658
1659byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1660{
1661 word Info;
1662 byte i;
1663
1664 dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1665
1666 Info = _WRONG_IDENTIFIER;
1667 if(a) {
1668 Info = 0;
1669 a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1670 a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1671 dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1672 if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1673 a->Info_Mask[appl->Id-1] |= 0x10; /* call progression infos */
1674 }
1675
1676 /* check if external controller listen and switch listen on or off*/
1677 if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1678 if(a->profile.Global_Options & ON_BOARD_CODEC) {
1679 dummy_plci.State = IDLE;
1680 a->codec_listen[appl->Id-1] = &dummy_plci;
1681 a->TelOAD[0] = (byte)(parms[3].length);
1682 for(i=1;parms[3].length>=i && i<22;i++) {
1683 a->TelOAD[i] = parms[3].info[i];
1684 }
1685 a->TelOAD[i] = 0;
1686 a->TelOSA[0] = (byte)(parms[4].length);
1687 for(i=1;parms[4].length>=i && i<22;i++) {
1688 a->TelOSA[i] = parms[4].info[i];
1689 }
1690 a->TelOSA[i] = 0;
1691 }
1692 else Info = 0x2002; /* wrong controller, codec not supported */
1693 }
1694 else{ /* clear listen */
1695 a->codec_listen[appl->Id-1] = (PLCI *)0;
1696 }
1697 }
1698 sendf(appl,
1699 _LISTEN_R|CONFIRM,
1700 Id,
1701 Number,
1702 "w",Info);
1703
1704 if (a) listen_check(a);
1705 return FALSE;
1706}
1707
1708byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1709{
1710 word i;
1711 API_PARSE * ai;
1712 PLCI * rc_plci = NULL;
1713 API_PARSE ai_parms[5];
1714 word Info = 0;
1715
1716 dbug(1,dprintf("info_req"));
1717 for(i=0;i<5;i++) ai_parms[i].length = 0;
1718
1719 ai = &msg[1];
1720
1721 if(ai->length)
1722 {
1723 if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1724 {
1725 dbug(1,dprintf("AddInfo wrong"));
1726 Info = _WRONG_MESSAGE_FORMAT;
1727 }
1728 }
1729 if(!a) Info = _WRONG_STATE;
1730
1731 if(!Info && plci)
1732 { /* no fac, with CPN, or KEY */
1733 rc_plci = plci;
1734 if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1735 {
1736 /* overlap sending option */
1737 dbug(1,dprintf("OvlSnd"));
1738 add_s(plci,CPN,&msg[0]);
1739 add_s(plci,KEY,&ai_parms[1]);
1740 sig_req(plci,INFO_REQ,0);
1741 send_req(plci);
1742 return FALSE;
1743 }
1744
1745 if(plci->State && ai_parms[2].length)
1746 {
1747 /* User_Info option */
1748 dbug(1,dprintf("UUI"));
1749 add_s(plci,UUI,&ai_parms[2]);
1750 sig_req(plci,USER_DATA,0);
1751 }
1752 else if(plci->State && ai_parms[3].length)
1753 {
1754 /* Facility option */
1755 dbug(1,dprintf("FAC"));
1756 add_s(plci,CPN,&msg[0]);
1757 add_ai(plci, &msg[1]);
1758 sig_req(plci,FACILITY_REQ,0);
1759 }
1760 else
1761 {
1762 Info = _WRONG_STATE;
1763 }
1764 }
1765 else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1766 {
1767 /* NCR_Facility option -> send UUI and Keypad too */
1768 dbug(1,dprintf("NCR_FAC"));
1769 if((i=get_plci(a)))
1770 {
1771 rc_plci = &a->plci[i-1];
1772 appl->NullCREnable = TRUE;
1773 rc_plci->internal_command = C_NCR_FAC_REQ;
1774 rc_plci->appl = appl;
1775 add_p(rc_plci,CAI,"\x01\x80");
1776 add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1777 sig_req(rc_plci,ASSIGN,DSIG_ID);
1778 send_req(rc_plci);
1779 }
1780 else
1781 {
1782 Info = _OUT_OF_PLCI;
1783 }
1784
1785 if(!Info)
1786 {
1787 add_s(rc_plci,CPN,&msg[0]);
1788 add_ai(rc_plci, &msg[1]);
1789 sig_req(rc_plci,NCR_FACILITY,0);
1790 send_req(rc_plci);
1791 return FALSE;
1792 /* for application controlled supplementary services */
1793 }
1794 }
1795
1796 if (!rc_plci)
1797 {
1798 Info = _WRONG_MESSAGE_FORMAT;
1799 }
1800
1801 if(!Info)
1802 {
1803 send_req(rc_plci);
1804 }
1805 else
1806 { /* appl is not assigned to a PLCI or error condition */
1807 dbug(1,dprintf("localInfoCon"));
1808 sendf(appl,
1809 _INFO_R|CONFIRM,
1810 Id,
1811 Number,
1812 "w",Info);
1813 }
1814 return FALSE;
1815}
1816
1817byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1818{
1819 dbug(1,dprintf("info_res"));
1820 return FALSE;
1821}
1822
1823byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1824{
1825 word Info;
1826 byte ret;
1827
1828 dbug(1,dprintf("alert_req"));
1829
1830 Info = _WRONG_IDENTIFIER;
1831 ret = FALSE;
1832 if(plci) {
1833 Info = _ALERT_IGNORED;
1834 if(plci->State!=INC_CON_ALERT) {
1835 Info = _WRONG_STATE;
1836 if(plci->State==INC_CON_PENDING) {
1837 Info = 0;
1838 plci->State=INC_CON_ALERT;
1839 add_ai(plci, &msg[0]);
1840 sig_req(plci,CALL_ALERT,0);
1841 ret = 1;
1842 }
1843 }
1844 }
1845 sendf(appl,
1846 _ALERT_R|CONFIRM,
1847 Id,
1848 Number,
1849 "w",Info);
1850 return ret;
1851}
1852
1853byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1854{
1855 word Info = 0;
1856 word i = 0;
1857
1858 word selector;
1859 word SSreq;
1860 long relatedPLCIvalue;
1861 DIVA_CAPI_ADAPTER * relatedadapter;
1862 byte * SSparms = "";
1863 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1864 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1865 API_PARSE * parms;
1866 API_PARSE ss_parms[11];
1867 PLCI *rplci;
1868 byte cai[15];
1869 dword d;
1870 API_PARSE dummy;
1871
1872 dbug(1,dprintf("facility_req"));
1873 for(i=0;i<9;i++) ss_parms[i].length = 0;
1874
1875 parms = &msg[1];
1876
1877 if(!a)
1878 {
1879 dbug(1,dprintf("wrong Ctrl"));
1880 Info = _WRONG_IDENTIFIER;
1881 }
1882
1883 selector = GET_WORD(msg[0].info);
1884
1885 if(!Info)
1886 {
1887 switch(selector)
1888 {
1889 case SELECTOR_HANDSET:
1890 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1891 break;
1892
1893 case SELECTOR_SU_SERV:
1894 if(!msg[1].length)
1895 {
1896 Info = _WRONG_MESSAGE_FORMAT;
1897 break;
1898 }
1899 SSreq = GET_WORD(&(msg[1].info[1]));
1900 PUT_WORD(&RCparms[1],SSreq);
1901 SSparms = RCparms;
1902 switch(SSreq)
1903 {
1904 case S_GET_SUPPORTED_SERVICES:
1905 if((i=get_plci(a)))
1906 {
1907 rplci = &a->plci[i-1];
1908 rplci->appl = appl;
1909 add_p(rplci,CAI,"\x01\x80");
1910 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1911 sig_req(rplci,ASSIGN,DSIG_ID);
1912 send_req(rplci);
1913 }
1914 else
1915 {
1916 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1917 SSparms = (byte *)SSstruct;
1918 break;
1919 }
1920 rplci->internal_command = GETSERV_REQ_PEND;
1921 rplci->number = Number;
1922 rplci->appl = appl;
1923 sig_req(rplci,S_SUPPORTED,0);
1924 send_req(rplci);
1925 return FALSE;
1926 break;
1927
1928 case S_LISTEN:
1929 if(parms->length==7)
1930 {
1931 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1932 {
1933 dbug(1,dprintf("format wrong"));
1934 Info = _WRONG_MESSAGE_FORMAT;
1935 break;
1936 }
1937 }
1938 else
1939 {
1940 Info = _WRONG_MESSAGE_FORMAT;
1941 break;
1942 }
1943 a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1944 if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1945 {
1946 if((i=get_plci(a)))
1947 {
1948 rplci = &a->plci[i-1];
1949 rplci->appl = appl;
1950 add_p(rplci,CAI,"\x01\x80");
1951 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1952 sig_req(rplci,ASSIGN,DSIG_ID);
1953 send_req(rplci);
1954 }
1955 else
1956 {
1957 break;
1958 }
1959 rplci->internal_command = GET_MWI_STATE;
1960 rplci->number = Number;
1961 sig_req(rplci,MWI_POLL,0);
1962 send_req(rplci);
1963 }
1964 break;
1965
1966 case S_HOLD:
1967 api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1968 if(plci && plci->State && plci->SuppState==IDLE)
1969 {
1970 plci->SuppState = HOLD_REQUEST;
1971 plci->command = C_HOLD_REQ;
1972 add_s(plci,CAI,&ss_parms[1]);
1973 sig_req(plci,CALL_HOLD,0);
1974 send_req(plci);
1975 return FALSE;
1976 }
1977 else Info = 0x3010; /* wrong state */
1978 break;
1979 case S_RETRIEVE:
1980 if(plci && plci->State && plci->SuppState==CALL_HELD)
1981 {
1982 if(Id & EXT_CONTROLLER)
1983 {
1984 if(AdvCodecSupport(a, plci, appl, 0))
1985 {
1986 Info = 0x3010; /* wrong state */
1987 break;
1988 }
1989 }
1990 else plci->tel = 0;
1991
1992 plci->SuppState = RETRIEVE_REQUEST;
1993 plci->command = C_RETRIEVE_REQ;
1994 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1995 {
1996 plci->spoofed_msg = CALL_RETRIEVE;
1997 plci->internal_command = BLOCK_PLCI;
1998 plci->command = 0;
1999 dbug(1,dprintf("Spoof"));
2000 return FALSE;
2001 }
2002 else
2003 {
2004 sig_req(plci,CALL_RETRIEVE,0);
2005 send_req(plci);
2006 return FALSE;
2007 }
2008 }
2009 else Info = 0x3010; /* wrong state */
2010 break;
2011 case S_SUSPEND:
2012 if(parms->length)
2013 {
2014 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2015 {
2016 dbug(1,dprintf("format wrong"));
2017 Info = _WRONG_MESSAGE_FORMAT;
2018 break;
2019 }
2020 }
2021 if(plci && plci->State)
2022 {
2023 add_s(plci,CAI,&ss_parms[2]);
2024 plci->command = SUSPEND_REQ;
2025 sig_req(plci,SUSPEND,0);
2026 plci->State = SUSPENDING;
2027 send_req(plci);
2028 }
2029 else Info = 0x3010; /* wrong state */
2030 break;
2031
2032 case S_RESUME:
2033 if(!(i=get_plci(a)) )
2034 {
2035 Info = _OUT_OF_PLCI;
2036 break;
2037 }
2038 rplci = &a->plci[i-1];
2039 rplci->appl = appl;
2040 rplci->number = Number;
2041 rplci->tel = 0;
2042 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2043 /* check 'external controller' bit for codec support */
2044 if(Id & EXT_CONTROLLER)
2045 {
2046 if(AdvCodecSupport(a, rplci, appl, 0) )
2047 {
2048 rplci->Id = 0;
2049 Info = 0x300A;
2050 break;
2051 }
2052 }
2053 if(parms->length)
2054 {
2055 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2056 {
2057 dbug(1,dprintf("format wrong"));
2058 rplci->Id = 0;
2059 Info = _WRONG_MESSAGE_FORMAT;
2060 break;
2061 }
2062 }
2063 dummy.length = 0;
2064 dummy.info = "\x00";
2065 add_b1(rplci, &dummy, 0, 0);
2066 if (a->Info_Mask[appl->Id-1] & 0x200)
2067 {
2068 /* early B3 connect (CIP mask bit 9) no release after a disc */
2069 add_p(rplci,LLI,"\x01\x01");
2070 }
2071 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2072 sig_req(rplci,ASSIGN,DSIG_ID);
2073 send_req(rplci);
2074 add_s(rplci,CAI,&ss_parms[2]);
2075 rplci->command = RESUME_REQ;
2076 sig_req(rplci,RESUME,0);
2077 rplci->State = RESUMING;
2078 send_req(rplci);
2079 break;
2080
2081 case S_CONF_BEGIN: /* Request */
2082 case S_CONF_DROP:
2083 case S_CONF_ISOLATE:
2084 case S_CONF_REATTACH:
2085 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2086 {
2087 dbug(1,dprintf("format wrong"));
2088 Info = _WRONG_MESSAGE_FORMAT;
2089 break;
2090 }
2091 if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2092 {
2093 d = GET_DWORD(ss_parms[2].info);
2094 if(d>=0x80)
2095 {
2096 dbug(1,dprintf("format wrong"));
2097 Info = _WRONG_MESSAGE_FORMAT;
2098 break;
2099 }
2100 plci->ptyState = (byte)SSreq;
2101 plci->command = 0;
2102 cai[0] = 2;
2103 switch(SSreq)
2104 {
2105 case S_CONF_BEGIN:
2106 cai[1] = CONF_BEGIN;
2107 plci->internal_command = CONF_BEGIN_REQ_PEND;
2108 break;
2109 case S_CONF_DROP:
2110 cai[1] = CONF_DROP;
2111 plci->internal_command = CONF_DROP_REQ_PEND;
2112 break;
2113 case S_CONF_ISOLATE:
2114 cai[1] = CONF_ISOLATE;
2115 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2116 break;
2117 case S_CONF_REATTACH:
2118 cai[1] = CONF_REATTACH;
2119 plci->internal_command = CONF_REATTACH_REQ_PEND;
2120 break;
2121 }
2122 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2123 add_p(plci,CAI,cai);
2124 sig_req(plci,S_SERVICE,0);
2125 send_req(plci);
2126 return FALSE;
2127 }
2128 else Info = 0x3010; /* wrong state */
2129 break;
2130
2131 case S_ECT:
2132 case S_3PTY_BEGIN:
2133 case S_3PTY_END:
2134 case S_CONF_ADD:
2135 if(parms->length==7)
2136 {
2137 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2138 {
2139 dbug(1,dprintf("format wrong"));
2140 Info = _WRONG_MESSAGE_FORMAT;
2141 break;
2142 }
2143 }
2144 else if(parms->length==8) /* workaround for the T-View-S */
2145 {
2146 if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2147 {
2148 dbug(1,dprintf("format wrong"));
2149 Info = _WRONG_MESSAGE_FORMAT;
2150 break;
2151 }
2152 }
2153 else
2154 {
2155 Info = _WRONG_MESSAGE_FORMAT;
2156 break;
2157 }
2158 if(!msg[1].length)
2159 {
2160 Info = _WRONG_MESSAGE_FORMAT;
2161 break;
2162 }
2163 if (!plci)
2164 {
2165 Info = _WRONG_IDENTIFIER;
2166 break;
2167 }
2168 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2169 relatedPLCIvalue &= 0x0000FFFF;
2170 dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2171 /* controller starts with 0 up to (max_adapter - 1) */
2172 if (((relatedPLCIvalue & 0x7f) == 0)
2173 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2174 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2175 {
2176 if(SSreq==S_3PTY_END)
2177 {
2178 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2179 rplci = plci;
2180 }
2181 else
2182 {
2183 Info = 0x3010; /* wrong state */
2184 break;
2185 }
2186 }
2187 else
2188 {
2189 relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2190 relatedPLCIvalue >>=8;
2191 /* find PLCI PTR*/
2192 for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2193 {
2194 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2195 {
2196 rplci = &relatedadapter->plci[i];
2197 }
2198 }
2199 if(!rplci || !relatedPLCIvalue)
2200 {
2201 if(SSreq==S_3PTY_END)
2202 {
2203 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2204 rplci = plci;
2205 }
2206 else
2207 {
2208 Info = 0x3010; /* wrong state */
2209 break;
2210 }
2211 }
2212 }
2213/*
2214 dbug(1,dprintf("rplci:%x",rplci));
2215 dbug(1,dprintf("plci:%x",plci));
2216 dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2217 dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2218 dbug(1,dprintf("SSreq:%x",SSreq));
2219 dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2220 dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2221 dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2222*/
2223 /* send PTY/ECT req, cannot check all states because of US stuff */
2224 if( !rplci->internal_command && rplci->appl )
2225 {
2226 plci->command = 0;
2227 rplci->relatedPTYPLCI = plci;
2228 plci->relatedPTYPLCI = rplci;
2229 rplci->ptyState = (byte)SSreq;
2230 if(SSreq==S_ECT)
2231 {
2232 rplci->internal_command = ECT_REQ_PEND;
2233 cai[1] = ECT_EXECUTE;
2234
2235 rplci->vswitchstate=0;
2236 rplci->vsprot=0;
2237 rplci->vsprotdialect=0;
2238 plci->vswitchstate=0;
2239 plci->vsprot=0;
2240 plci->vsprotdialect=0;
2241
2242 }
2243 else if(SSreq==S_CONF_ADD)
2244 {
2245 rplci->internal_command = CONF_ADD_REQ_PEND;
2246 cai[1] = CONF_ADD;
2247 }
2248 else
2249 {
2250 rplci->internal_command = PTY_REQ_PEND;
2251 cai[1] = (byte)(SSreq-3);
2252 }
2253 rplci->number = Number;
2254 if(plci!=rplci) /* explicit invocation */
2255 {
2256 cai[0] = 2;
2257 cai[2] = plci->Sig.Id;
2258 dbug(1,dprintf("explicit invocation"));
2259 }
2260 else
2261 {
2262 dbug(1,dprintf("implicit invocation"));
2263 cai[0] = 1;
2264 }
2265 add_p(rplci,CAI,cai);
2266 sig_req(rplci,S_SERVICE,0);
2267 send_req(rplci);
2268 return FALSE;
2269 }
2270 else
2271 {
2272 dbug(0,dprintf("Wrong line"));
2273 Info = 0x3010; /* wrong state */
2274 break;
2275 }
2276 break;
2277
2278 case S_CALL_DEFLECTION:
2279 if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2280 {
2281 dbug(1,dprintf("format wrong"));
2282 Info = _WRONG_MESSAGE_FORMAT;
2283 break;
2284 }
2285 if (!plci)
2286 {
2287 Info = _WRONG_IDENTIFIER;
2288 break;
2289 }
2290 /* reuse unused screening indicator */
2291 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2292 plci->command = 0;
2293 plci->internal_command = CD_REQ_PEND;
2294 appl->CDEnable = TRUE;
2295 cai[0] = 1;
2296 cai[1] = CALL_DEFLECTION;
2297 add_p(plci,CAI,cai);
2298 add_p(plci,CPN,ss_parms[3].info);
2299 sig_req(plci,S_SERVICE,0);
2300 send_req(plci);
2301 return FALSE;
2302 break;
2303
2304 case S_CALL_FORWARDING_START:
2305 if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2306 {
2307 dbug(1,dprintf("format wrong"));
2308 Info = _WRONG_MESSAGE_FORMAT;
2309 break;
2310 }
2311
2312 if((i=get_plci(a)))
2313 {
2314 rplci = &a->plci[i-1];
2315 rplci->appl = appl;
2316 add_p(rplci,CAI,"\x01\x80");
2317 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2318 sig_req(rplci,ASSIGN,DSIG_ID);
2319 send_req(rplci);
2320 }
2321 else
2322 {
2323 Info = _OUT_OF_PLCI;
2324 break;
2325 }
2326
2327 /* reuse unused screening indicator */
2328 rplci->internal_command = CF_START_PEND;
2329 rplci->appl = appl;
2330 rplci->number = Number;
2331 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2332 cai[0] = 2;
2333 cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2334 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2335 add_p(rplci,CAI,cai);
2336 add_p(rplci,OAD,ss_parms[5].info);
2337 add_p(rplci,CPN,ss_parms[6].info);
2338 sig_req(rplci,S_SERVICE,0);
2339 send_req(rplci);
2340 return FALSE;
2341 break;
2342
2343 case S_INTERROGATE_DIVERSION:
2344 case S_INTERROGATE_NUMBERS:
2345 case S_CALL_FORWARDING_STOP:
2346 case S_CCBS_REQUEST:
2347 case S_CCBS_DEACTIVATE:
2348 case S_CCBS_INTERROGATE:
2349 switch(SSreq)
2350 {
2351 case S_INTERROGATE_NUMBERS:
2352 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2353 {
2354 dbug(0,dprintf("format wrong"));
2355 Info = _WRONG_MESSAGE_FORMAT;
2356 }
2357 break;
2358 case S_CCBS_REQUEST:
2359 case S_CCBS_DEACTIVATE:
2360 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2361 {
2362 dbug(0,dprintf("format wrong"));
2363 Info = _WRONG_MESSAGE_FORMAT;
2364 }
2365 break;
2366 case S_CCBS_INTERROGATE:
2367 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2368 {
2369 dbug(0,dprintf("format wrong"));
2370 Info = _WRONG_MESSAGE_FORMAT;
2371 }
2372 break;
2373 default:
2374 if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2375 {
2376 dbug(0,dprintf("format wrong"));
2377 Info = _WRONG_MESSAGE_FORMAT;
2378 break;
2379 }
2380 break;
2381 }
2382
2383 if(Info) break;
2384 if((i=get_plci(a)))
2385 {
2386 rplci = &a->plci[i-1];
2387 switch(SSreq)
2388 {
2389 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2390 cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2391 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2392 break;
2393 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2394 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2395 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2396 break;
2397 case S_CALL_FORWARDING_STOP:
2398 rplci->internal_command = CF_STOP_PEND;
2399 cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2400 break;
2401 case S_CCBS_REQUEST:
2402 cai[1] = CCBS_REQUEST;
2403 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2404 break;
2405 case S_CCBS_DEACTIVATE:
2406 cai[1] = CCBS_DEACTIVATE;
2407 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2408 break;
2409 case S_CCBS_INTERROGATE:
2410 cai[1] = CCBS_INTERROGATE;
2411 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2412 break;
2413 default:
2414 cai[1] = 0;
2415 break;
2416 }
2417 rplci->appl = appl;
2418 rplci->number = Number;
2419 add_p(rplci,CAI,"\x01\x80");
2420 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2421 sig_req(rplci,ASSIGN,DSIG_ID);
2422 send_req(rplci);
2423 }
2424 else
2425 {
2426 Info = _OUT_OF_PLCI;
2427 break;
2428 }
2429
2430 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2431 switch(SSreq)
2432 {
2433 case S_INTERROGATE_NUMBERS:
2434 cai[0] = 1;
2435 add_p(rplci,CAI,cai);
2436 break;
2437 case S_CCBS_REQUEST:
2438 case S_CCBS_DEACTIVATE:
2439 cai[0] = 3;
2440 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2441 add_p(rplci,CAI,cai);
2442 break;
2443 case S_CCBS_INTERROGATE:
2444 cai[0] = 3;
2445 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2446 add_p(rplci,CAI,cai);
2447 add_p(rplci,OAD,ss_parms[4].info);
2448 break;
2449 default:
2450 cai[0] = 2;
2451 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2452 add_p(rplci,CAI,cai);
2453 add_p(rplci,OAD,ss_parms[5].info);
2454 break;
2455 }
2456
2457 sig_req(rplci,S_SERVICE,0);
2458 send_req(rplci);
2459 return FALSE;
2460 break;
2461
2462 case S_MWI_ACTIVATE:
2463 if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2464 {
2465 dbug(1,dprintf("format wrong"));
2466 Info = _WRONG_MESSAGE_FORMAT;
2467 break;
2468 }
2469 if(!plci)
2470 {
2471 if((i=get_plci(a)))
2472 {
2473 rplci = &a->plci[i-1];
2474 rplci->appl = appl;
2475 rplci->cr_enquiry=TRUE;
2476 add_p(rplci,CAI,"\x01\x80");
2477 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2478 sig_req(rplci,ASSIGN,DSIG_ID);
2479 send_req(rplci);
2480 }
2481 else
2482 {
2483 Info = _OUT_OF_PLCI;
2484 break;
2485 }
2486 }
2487 else
2488 {
2489 rplci = plci;
2490 rplci->cr_enquiry=FALSE;
2491 }
2492
2493 rplci->command = 0;
2494 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2495 rplci->appl = appl;
2496 rplci->number = Number;
2497
2498 cai[0] = 13;
2499 cai[1] = ACTIVATION_MWI; /* Function */
2500 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2501 PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2502 PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2503 PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2504 PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2505 add_p(rplci,CAI,cai);
2506 add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2507 add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2508 add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2509 add_p(rplci,UID,ss_parms[10].info); /* Time */
2510 sig_req(rplci,S_SERVICE,0);
2511 send_req(rplci);
2512 return FALSE;
2513
2514 case S_MWI_DEACTIVATE:
2515 if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2516 {
2517 dbug(1,dprintf("format wrong"));
2518 Info = _WRONG_MESSAGE_FORMAT;
2519 break;
2520 }
2521 if(!plci)
2522 {
2523 if((i=get_plci(a)))
2524 {
2525 rplci = &a->plci[i-1];
2526 rplci->appl = appl;
2527 rplci->cr_enquiry=TRUE;
2528 add_p(rplci,CAI,"\x01\x80");
2529 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2530 sig_req(rplci,ASSIGN,DSIG_ID);
2531 send_req(rplci);
2532 }
2533 else
2534 {
2535 Info = _OUT_OF_PLCI;
2536 break;
2537 }
2538 }
2539 else
2540 {
2541 rplci = plci;
2542 rplci->cr_enquiry=FALSE;
2543 }
2544
2545 rplci->command = 0;
2546 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2547 rplci->appl = appl;
2548 rplci->number = Number;
2549
2550 cai[0] = 5;
2551 cai[1] = DEACTIVATION_MWI; /* Function */
2552 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2553 PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2554 add_p(rplci,CAI,cai);
2555 add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2556 add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2557 sig_req(rplci,S_SERVICE,0);
2558 send_req(rplci);
2559 return FALSE;
2560
2561 default:
2562 Info = 0x300E; /* not supported */
2563 break;
2564 }
2565 break; /* case SELECTOR_SU_SERV: end */
2566
2567
2568 case SELECTOR_DTMF:
2569 return (dtmf_request (Id, Number, a, plci, appl, msg));
2570
2571
2572
2573 case SELECTOR_LINE_INTERCONNECT:
2574 return (mixer_request (Id, Number, a, plci, appl, msg));
2575
2576
2577
2578 case PRIV_SELECTOR_ECHO_CANCELLER:
2579 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2580 return (ec_request (Id, Number, a, plci, appl, msg));
2581
2582 case SELECTOR_ECHO_CANCELLER:
2583 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2584 return (ec_request (Id, Number, a, plci, appl, msg));
2585
2586
2587 case SELECTOR_V42BIS:
2588 default:
2589 Info = _FACILITY_NOT_SUPPORTED;
2590 break;
2591 } /* end of switch(selector) */
2592 }
2593
2594 dbug(1,dprintf("SendFacRc"));
2595 sendf(appl,
2596 _FACILITY_R|CONFIRM,
2597 Id,
2598 Number,
2599 "wws",Info,selector,SSparms);
2600 return FALSE;
2601}
2602
2603byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
2604{
2605 dbug(1,dprintf("facility_res"));
2606 return FALSE;
2607}
2608
2609byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2610{
2611 word Info = 0;
2612 byte req;
2613 byte len;
2614 word w;
2615 word fax_control_bits, fax_feature_bits, fax_info_change;
2616 API_PARSE * ncpi;
2617 byte pvc[2];
2618
2619 API_PARSE fax_parms[9];
2620 word i;
2621
2622
2623 dbug(1,dprintf("connect_b3_req"));
2624 if(plci)
2625 {
2626 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2627 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2628 {
2629 Info = _WRONG_STATE;
2630 }
2631 else
2632 {
2633 /* local reply if assign unsuccessfull
2634 or B3 protocol allows only one layer 3 connection
2635 and already connected
2636 or B2 protocol not any LAPD
2637 and connect_b3_req contradicts originate/answer direction */
2638 if (!plci->NL.Id
2639 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2640 && ((plci->channels != 0)
2641 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2642 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2643 {
2644 dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2645 plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2646 Info = _WRONG_STATE;
2647 sendf(appl,
2648 _CONNECT_B3_R|CONFIRM,
2649 Id,
2650 Number,
2651 "w",Info);
2652 return FALSE;
2653 }
2654 plci->requested_options_conn = 0;
2655
2656 req = N_CONNECT;
2657 ncpi = &parms[0];
2658 if(plci->B3_prot==2 || plci->B3_prot==3)
2659 {
2660 if(ncpi->length>2)
2661 {
2662 /* check for PVC */
2663 if(ncpi->info[2] || ncpi->info[3])
2664 {
2665 pvc[0] = ncpi->info[3];
2666 pvc[1] = ncpi->info[2];
2667 add_d(plci,2,pvc);
2668 req = N_RESET;
2669 }
2670 else
2671 {
2672 if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2673 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2674 }
2675 }
2676 }
2677 else if(plci->B3_prot==5)
2678 {
2679 if (plci->NL.Id && !plci->nl_remove_id)
2680 {
2681 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2682 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2683 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2684 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2685 {
2686 len = (byte)(&(((T30_INFO *) 0)->universal_6));
2687 fax_info_change = FALSE;
2688 if (ncpi->length >= 4)
2689 {
2690 w = GET_WORD(&ncpi->info[3]);
2691 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2692 {
2693 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2694 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2695 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2696 fax_info_change = TRUE;
2697 }
2698 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2699 if (w & 0x0002) /* Fax-polling request */
2700 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2701 if ((w & 0x0004) /* Request to send / poll another document */
2702 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2703 {
2704 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2705 }
2706 if (ncpi->length >= 6)
2707 {
2708 w = GET_WORD(&ncpi->info[5]);
2709 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2710 {
2711 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2712 fax_info_change = TRUE;
2713 }
2714
2715 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2716 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2717 {
2718 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2719 }
2720 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2721 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2722 {
2723 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2724 }
2725 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2726 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2727 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2728 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2729 {
2730 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2731 Info = _WRONG_MESSAGE_FORMAT;
2732 else
2733 {
2734 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2735 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2736 {
2737 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2738 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2739 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2740 }
2741 w = fax_parms[4].length;
2742 if (w > 20)
2743 w = 20;
2744 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2745 for (i = 0; i < w; i++)
2746 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2747 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2748 len = (byte)(((T30_INFO *) 0)->station_id + 20);
2749 w = fax_parms[5].length;
2750 if (w > 20)
2751 w = 20;
2752 plci->fax_connect_info_buffer[len++] = (byte) w;
2753 for (i = 0; i < w; i++)
2754 plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2755 w = fax_parms[6].length;
2756 if (w > 20)
2757 w = 20;
2758 plci->fax_connect_info_buffer[len++] = (byte) w;
2759 for (i = 0; i < w; i++)
2760 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2761 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2762 & (1L << PRIVATE_FAX_NONSTANDARD))
2763 {
2764 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2765 {
2766 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2767 plci->fax_connect_info_buffer[len++] = 0;
2768 }
2769 else
2770 {
2771 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2772 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2773 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2774 for (i = 0; i < fax_parms[7].length; i++)
2775 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2776 }
2777 }
2778 }
2779 }
2780 else
2781 {
2782 len = (byte)(&(((T30_INFO *) 0)->universal_6));
2783 }
2784 fax_info_change = TRUE;
2785
2786 }
2787 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2788 {
2789 PUT_WORD (&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2790 fax_info_change = TRUE;
2791 }
2792 }
2793 if (Info == GOOD)
2794 {
2795 plci->fax_connect_info_length = len;
2796 if (fax_info_change)
2797 {
2798 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2799 {
2800 start_internal_command (Id, plci, fax_connect_info_command);
2801 return FALSE;
2802 }
2803 else
2804 {
2805 start_internal_command (Id, plci, fax_adjust_b23_command);
2806 return FALSE;
2807 }
2808 }
2809 }
2810 }
2811 else Info = _WRONG_STATE;
2812 }
2813 else Info = _WRONG_STATE;
2814 }
2815
2816 else if (plci->B3_prot == B3_RTP)
2817 {
2818 plci->internal_req_buffer[0] = ncpi->length + 1;
2819 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2820 for (w = 0; w < ncpi->length; w++)
2821 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2822 start_internal_command (Id, plci, rtp_connect_b3_req_command);
2823 return FALSE;
2824 }
2825
2826 if(!Info)
2827 {
2828 nl_req_ncci(plci,req,0);
2829 return 1;
2830 }
2831 }
2832 }
2833 else Info = _WRONG_IDENTIFIER;
2834
2835 sendf(appl,
2836 _CONNECT_B3_R|CONFIRM,
2837 Id,
2838 Number,
2839 "w",Info);
2840 return FALSE;
2841}
2842
2843byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2844{
2845 word ncci;
2846 API_PARSE * ncpi;
2847 byte req;
2848
2849 word w;
2850
2851
2852 API_PARSE fax_parms[9];
2853 word i;
2854 byte len;
2855
2856
2857 dbug(1,dprintf("connect_b3_res"));
2858
2859 ncci = (word)(Id>>16);
2860 if(plci && ncci) {
2861 if(a->ncci_state[ncci]==INC_CON_PENDING) {
2862 if (GET_WORD (&parms[0].info[0]) != 0)
2863 {
2864 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2865 channel_request_xon (plci, a->ncci_ch[ncci]);
2866 channel_xmit_xon (plci);
2867 cleanup_ncci_data (plci, ncci);
2868 nl_req_ncci(plci,N_DISC,(byte)ncci);
2869 return 1;
2870 }
2871 a->ncci_state[ncci] = INC_ACT_PENDING;
2872
2873 req = N_CONNECT_ACK;
2874 ncpi = &parms[1];
2875 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2876 {
2877
2878 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2879 & (1L << PRIVATE_FAX_NONSTANDARD))
2880 {
2881 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2882 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2883 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2884 {
2885 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2886 if (plci->fax_connect_info_length < len)
2887 {
2888 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2889 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2890 }
2891 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2892 {
2893 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2894 }
2895 else
2896 {
2897 if (plci->fax_connect_info_length <= len)
2898 plci->fax_connect_info_buffer[len] = 0;
2899 len += 1 + plci->fax_connect_info_buffer[len];
2900 if (plci->fax_connect_info_length <= len)
2901 plci->fax_connect_info_buffer[len] = 0;
2902 len += 1 + plci->fax_connect_info_buffer[len];
2903 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2904 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2905 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2906 for (i = 0; i < fax_parms[7].length; i++)
2907 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2908 }
2909 plci->fax_connect_info_length = len;
2910 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2911 start_internal_command (Id, plci, fax_connect_ack_command);
2912 return FALSE;
2913 }
2914 }
2915
2916 nl_req_ncci(plci,req,(byte)ncci);
2917 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2918 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2919 {
2920 if (plci->B3_prot == 4)
2921 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2922 else
2923 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2924 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2925 }
2926 }
2927
2928 else if (plci->B3_prot == B3_RTP)
2929 {
2930 plci->internal_req_buffer[0] = ncpi->length + 1;
2931 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2932 for (w = 0; w < ncpi->length; w++)
2933 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2934 start_internal_command (Id, plci, rtp_connect_b3_res_command);
2935 return FALSE;
2936 }
2937
2938 else
2939 {
2940 if(ncpi->length>2) {
2941 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2942 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2943 }
2944 nl_req_ncci(plci,req,(byte)ncci);
2945 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2946 if (plci->adjust_b_restore)
2947 {
2948 plci->adjust_b_restore = FALSE;
2949 start_internal_command (Id, plci, adjust_b_restore);
2950 }
2951 }
2952 return 1;
2953 }
2954 }
2955 return FALSE;
2956}
2957
2958byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2959{
2960 word ncci;
2961
2962 ncci = (word)(Id>>16);
2963 dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2964
2965 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2966 && (plci->State != OUTG_DIS_PENDING))
2967 {
2968 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2969 a->ncci_state[ncci] = CONNECTED;
2970 if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2971 channel_request_xon (plci, a->ncci_ch[ncci]);
2972 channel_xmit_xon (plci);
2973 }
2974 }
2975 return FALSE;
2976}
2977
2978byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2979{
2980 word Info;
2981 word ncci;
2982 API_PARSE * ncpi;
2983
2984 dbug(1,dprintf("disconnect_b3_req"));
2985
2986 Info = _WRONG_IDENTIFIER;
2987 ncci = (word)(Id>>16);
2988 if (plci && ncci)
2989 {
2990 Info = _WRONG_STATE;
2991 if ((a->ncci_state[ncci] == CONNECTED)
2992 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2993 || (a->ncci_state[ncci] == INC_CON_PENDING)
2994 || (a->ncci_state[ncci] == INC_ACT_PENDING))
2995 {
2996 a->ncci_state[ncci] = OUTG_DIS_PENDING;
2997 channel_request_xon (plci, a->ncci_ch[ncci]);
2998 channel_xmit_xon (plci);
2999
3000 if (a->ncci[ncci].data_pending
3001 && ((plci->B3_prot == B3_TRANSPARENT)
3002 || (plci->B3_prot == B3_T30)
3003 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3004 {
3005 plci->send_disc = (byte)ncci;
3006 plci->command = 0;
3007 return FALSE;
3008 }
3009 else
3010 {
3011 cleanup_ncci_data (plci, ncci);
3012
3013 if(plci->B3_prot==2 || plci->B3_prot==3)
3014 {
3015 ncpi = &parms[0];
3016 if(ncpi->length>3)
3017 {
3018 add_d(plci, (word)(ncpi->length - 3) ,(byte *)&(ncpi->info[4]));
3019 }
3020 }
3021 nl_req_ncci(plci,N_DISC,(byte)ncci);
3022 }
3023 return 1;
3024 }
3025 }
3026 sendf(appl,
3027 _DISCONNECT_B3_R|CONFIRM,
3028 Id,
3029 Number,
3030 "w",Info);
3031 return FALSE;
3032}
3033
3034byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3035{
3036 word ncci;
3037 word i;
3038
3039 ncci = (word)(Id>>16);
3040 dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3041 if(plci && ncci) {
3042 plci->requested_options_conn = 0;
3043 plci->fax_connect_info_length = 0;
3044 plci->ncpi_state = 0x00;
3045 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3046 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3047 {
3048 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3049 }
3050 for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3051 if(i<MAX_CHANNELS_PER_PLCI) {
3052 if(plci->channels)plci->channels--;
3053 for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3054 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3055
3056 ncci_free_receive_buffers (plci, ncci);
3057
3058 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3059 if(plci->State == SUSPENDING){
3060 sendf(plci->appl,
3061 _FACILITY_I,
3062 Id & 0xffffL,
3063 0,
3064 "ws", (word)3, "\x03\x04\x00\x00");
3065 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3066 }
3067 plci_remove(plci);
3068 plci->State=IDLE;
3069 }
3070 }
3071 else
3072 {
3073 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3074 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3075 && (a->ncci_state[ncci] == INC_DIS_PENDING))
3076 {
3077 ncci_free_receive_buffers (plci, ncci);
3078
3079 nl_req_ncci(plci,N_EDATA,(byte)ncci);
3080
3081 plci->adapter->ncci_state[ncci] = IDLE;
3082 start_internal_command (Id, plci, fax_disconnect_command);
3083 return 1;
3084 }
3085 }
3086 }
3087 return FALSE;
3088}
3089
3090byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3091{
3092 NCCI *ncci_ptr;
3093 DATA_B3_DESC *data;
3094 word Info;
3095 word ncci;
3096 word i;
3097
3098 dbug(1,dprintf("data_b3_req"));
3099
3100 Info = _WRONG_IDENTIFIER;
3101 ncci = (word)(Id>>16);
3102 dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3103
3104 if (plci && ncci)
3105 {
3106 Info = _WRONG_STATE;
3107 if ((a->ncci_state[ncci] == CONNECTED)
3108 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3109 {
3110 /* queue data */
3111 ncci_ptr = &(a->ncci[ncci]);
3112 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3113 if (i >= MAX_DATA_B3)
3114 i -= MAX_DATA_B3;
3115 data = &(ncci_ptr->DBuffer[i]);
3116 data->Number = Number;
3117 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3118 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3119 {
3120
3121 data->P = (byte *)(*((dword *)(parms[0].info)));
3122
3123 }
3124 else
3125 data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3126 data->Length = GET_WORD(parms[1].info);
3127 data->Handle = GET_WORD(parms[2].info);
3128 data->Flags = GET_WORD(parms[3].info);
3129 (ncci_ptr->data_pending)++;
3130
3131 /* check for delivery confirmation */
3132 if (data->Flags & 0x0004)
3133 {
3134 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3135 if (i >= MAX_DATA_ACK)
3136 i -= MAX_DATA_ACK;
3137 ncci_ptr->DataAck[i].Number = data->Number;
3138 ncci_ptr->DataAck[i].Handle = data->Handle;
3139 (ncci_ptr->data_ack_pending)++;
3140 }
3141
3142 send_data(plci);
3143 return FALSE;
3144 }
3145 }
3146 if (appl)
3147 {
3148 if (plci)
3149 {
3150 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3151 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3152 {
3153
3154 TransmitBufferFree (appl, (byte *)(*((dword *)(parms[0].info))));
3155
3156 }
3157 }
3158 sendf(appl,
3159 _DATA_B3_R|CONFIRM,
3160 Id,
3161 Number,
3162 "ww",GET_WORD(parms[2].info),Info);
3163 }
3164 return FALSE;
3165}
3166
3167byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3168{
3169 word n;
3170 word ncci;
3171 word NCCIcode;
3172
3173 dbug(1,dprintf("data_b3_res"));
3174
3175 ncci = (word)(Id>>16);
3176 if(plci && ncci) {
3177 n = GET_WORD(parms[0].info);
3178 dbug(1,dprintf("free(%d)",n));
3179 NCCIcode = ncci | (((word) a->Id) << 8);
3180 if(n<appl->MaxBuffer &&
3181 appl->DataNCCI[n]==NCCIcode &&
3182 (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3183 dbug(1,dprintf("found"));
3184 appl->DataNCCI[n] = 0;
3185
3186 if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3187 channel_request_xon (plci, a->ncci_ch[ncci]);
3188 }
3189 channel_xmit_xon (plci);
3190
3191 if(appl->DataFlags[n] &4) {
3192 nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3193 return 1;
3194 }
3195 }
3196 }
3197 return FALSE;
3198}
3199
3200byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3201{
3202 word Info;
3203 word ncci;
3204
3205 dbug(1,dprintf("reset_b3_req"));
3206
3207 Info = _WRONG_IDENTIFIER;
3208 ncci = (word)(Id>>16);
3209 if(plci && ncci)
3210 {
3211 Info = _WRONG_STATE;
3212 switch (plci->B3_prot)
3213 {
3214 case B3_ISO8208:
3215 case B3_X25_DCE:
3216 if(a->ncci_state[ncci]==CONNECTED)
3217 {
3218 nl_req_ncci(plci,N_RESET,(byte)ncci);
3219 send_req(plci);
3220 Info = GOOD;
3221 }
3222 break;
3223 case B3_TRANSPARENT:
3224 if(a->ncci_state[ncci]==CONNECTED)
3225 {
3226 start_internal_command (Id, plci, reset_b3_command);
3227 Info = GOOD;
3228 }
3229 break;
3230 }
3231 }
3232 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3233 sendf(appl,
3234 _RESET_B3_R|CONFIRM,
3235 Id,
3236 Number,
3237 "w",Info);
3238 return FALSE;
3239}
3240
3241byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3242{
3243 word ncci;
3244
3245 dbug(1,dprintf("reset_b3_res"));
3246
3247 ncci = (word)(Id>>16);
3248 if(plci && ncci) {
3249 switch (plci->B3_prot)
3250 {
3251 case B3_ISO8208:
3252 case B3_X25_DCE:
3253 if(a->ncci_state[ncci]==INC_RES_PENDING)
3254 {
3255 a->ncci_state[ncci] = CONNECTED;
3256 nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3257 return TRUE;
3258 }
3259 break;
3260 }
3261 }
3262 return FALSE;
3263}
3264
3265byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3266{
3267 word ncci;
3268 API_PARSE * ncpi;
3269 byte req;
3270
3271 dbug(1,dprintf("connect_b3_t90_a_res"));
3272
3273 ncci = (word)(Id>>16);
3274 if(plci && ncci) {
3275 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3276 a->ncci_state[ncci] = CONNECTED;
3277 }
3278 else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3279 a->ncci_state[ncci] = CONNECTED;
3280
3281 req = N_CONNECT_ACK;
3282
3283 /* parms[0]==0 for CAPI original message definition! */
3284 if(parms[0].info) {
3285 ncpi = &parms[1];
3286 if(ncpi->length>2) {
3287 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3288 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3289 }
3290 }
3291 nl_req_ncci(plci,req,(byte)ncci);
3292 return 1;
3293 }
3294 }
3295 return FALSE;
3296}
3297
3298
3299byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
3300{
3301 word Info=0;
3302 word i;
3303 byte tel;
3304 API_PARSE bp_parms[7];
3305
3306 if(!plci || !msg)
3307 {
3308 Info = _WRONG_IDENTIFIER;
3309 }
3310 else
3311 {
3312 dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3313 msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3314 dbug(1,dprintf("PlciState=0x%x",plci->State));
3315 for(i=0;i<7;i++) bp_parms[i].length = 0;
3316
3317 /* check if no channel is open, no B3 connected only */
3318 if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3319 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3320 {
3321 Info = _WRONG_STATE;
3322 }
3323 /* check message format and fill bp_parms pointer */
3324 else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3325 {
3326 Info = _WRONG_MESSAGE_FORMAT;
3327 }
3328 else
3329 {
3330 if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3331 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3332 if(Id & EXT_CONTROLLER)
3333 {
3334 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3335 return 0;
3336 }
3337 plci->State=INC_CON_CONNECTED_ALERT;
3338 plci->appl = appl;
3339 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3340 dump_c_ind_mask (plci);
3341 for(i=0; i<max_appl; i++) /* disconnect the other appls */
3342 { /* its quasi a connect */
3343 if(test_c_ind_mask_bit (plci, i))
3344 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3345 }
3346 }
3347
3348 api_save_msg(msg, "s", &plci->saved_msg);
3349 tel = plci->tel;
3350 if(Id & EXT_CONTROLLER)
3351 {
3352 if(tel) /* external controller in use by this PLCI */
3353 {
3354 if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3355 {
3356 dbug(1,dprintf("Ext_Ctrl in use 1"));
3357 Info = _WRONG_STATE;
3358 }
3359 }
3360 else /* external controller NOT in use by this PLCI ? */
3361 {
3362 if(a->AdvSignalPLCI)
3363 {
3364 dbug(1,dprintf("Ext_Ctrl in use 2"));
3365 Info = _WRONG_STATE;
3366 }
3367 else /* activate the codec */
3368 {
3369 dbug(1,dprintf("Ext_Ctrl start"));
3370 if(AdvCodecSupport(a, plci, appl, 0) )
3371 {
3372 dbug(1,dprintf("Error in codec procedures"));
3373 Info = _WRONG_STATE;
3374 }
3375 else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3376 {
3377 plci->spoofed_msg = AWAITING_SELECT_B;
3378 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3379 plci->command = 0;
3380 dbug(1,dprintf("continue if codec loaded"));
3381 return FALSE;
3382 }
3383 }
3384 }
3385 }
3386 else /* external controller bit is OFF */
3387 {
3388 if(tel) /* external controller in use, need to switch off */
3389 {
3390 if(a->AdvSignalAppl==appl)
3391 {
3392 CodecIdCheck(a, plci);
3393 plci->tel = 0;
3394 plci->adv_nl = 0;
3395 dbug(1,dprintf("Ext_Ctrl disable"));
3396 }
3397 else
3398 {
3399 dbug(1,dprintf("Ext_Ctrl not requested"));
3400 }
3401 }
3402 }
3403 if (!Info)
3404 {
3405 if (plci->call_dir & CALL_DIR_OUT)
3406 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3407 else if (plci->call_dir & CALL_DIR_IN)
3408 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3409 start_internal_command (Id, plci, select_b_command);
3410 return FALSE;
3411 }
3412 }
3413 }
3414 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3415 return FALSE;
3416}
3417
3418byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3419{
3420 word command;
3421 word i;
3422 word ncci;
3423 API_PARSE * m;
3424 API_PARSE m_parms[5];
3425 word codec;
3426 byte req;
3427 byte ch;
3428 byte dir;
3429 static byte chi[2] = {0x01,0x00};
3430 static byte lli[2] = {0x01,0x00};
3431 static byte codec_cai[2] = {0x01,0x01};
3432 static byte null_msg = {0};
3433 static API_PARSE null_parms = { 0, &null_msg };
3434 PLCI * v_plci;
3435 word Info=0;
3436
3437 dbug(1,dprintf("manufacturer_req"));
3438 for(i=0;i<5;i++) m_parms[i].length = 0;
3439
3440 if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3441 Info = _WRONG_MESSAGE_FORMAT;
3442 }
3443 command = GET_WORD(parms[1].info);
3444 m = &parms[2];
3445 if (!Info)
3446 {
3447 switch(command) {
3448 case _DI_ASSIGN_PLCI:
3449 if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3450 Info = _WRONG_MESSAGE_FORMAT;
3451 break;
3452 }
3453 codec = GET_WORD(m_parms[0].info);
3454 ch = m_parms[1].info[0];
3455 dir = m_parms[2].info[0];
3456 if((i=get_plci(a))) {
3457 plci = &a->plci[i-1];
3458 plci->appl = appl;
3459 plci->command = _MANUFACTURER_R;
3460 plci->m_command = command;
3461 plci->number = Number;
3462 plci->State = LOCAL_CONNECT;
3463 Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3464 dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3465
3466 if((ch==1 || ch==2) && (dir<=2)) {
3467 chi[1] = (byte)(0x80|ch);
3468 lli[1] = 0;
3469 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3470 switch(codec)
3471 {
3472 case 0:
3473 Info = add_b1(plci,&m_parms[3],0,0);
3474 break;
3475 case 1:
3476 add_p(plci,CAI,codec_cai);
3477 break;
3478 /* manual 'swich on' to the codec support without signalling */
3479 /* first 'assign plci' with this function, then use */
3480 case 2:
3481 if(AdvCodecSupport(a, plci, appl, 0) ) {
3482 Info = _RESOURCE_ERROR;
3483 }
3484 else {
3485 Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3486 lli[1] = 0x10; /* local call codec stream */
3487 }
3488 break;
3489 }
3490
3491 plci->State = LOCAL_CONNECT;
3492 plci->manufacturer = TRUE;
3493 plci->command = _MANUFACTURER_R;
3494 plci->m_command = command;
3495 plci->number = Number;
3496
3497 if(!Info)
3498 {
3499 add_p(plci,LLI,lli);
3500 add_p(plci,CHI,chi);
3501 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3502 sig_req(plci,ASSIGN,DSIG_ID);
3503
3504 if(!codec)
3505 {
3506 Info = add_b23(plci,&m_parms[3]);
3507 if(!Info)
3508 {
3509 nl_req_ncci(plci,ASSIGN,0);
3510 send_req(plci);
3511 }
3512 }
3513 if(!Info)
3514 {
3515 dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3516 if (plci->spoofed_msg==SPOOFING_REQUIRED)
3517 {
3518 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3519 plci->spoofed_msg = AWAITING_MANUF_CON;
3520 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3521 plci->command = 0;
3522 send_req(plci);
3523 return FALSE;
3524 }
3525 if(dir==1) {
3526 sig_req(plci,CALL_REQ,0);
3527 }
3528 else if(!dir){
3529 sig_req(plci,LISTEN_REQ,0);
3530 }
3531 send_req(plci);
3532 }
3533 else
3534 {
3535 sendf(appl,
3536 _MANUFACTURER_R|CONFIRM,
3537 Id,
3538 Number,
3539 "dww",_DI_MANU_ID,command,Info);
3540 return 2;
3541 }
3542 }
3543 }
3544 }
3545 else Info = _OUT_OF_PLCI;
3546 break;
3547
3548 case _DI_IDI_CTRL:
3549 if(!plci)
3550 {
3551 Info = _WRONG_IDENTIFIER;
3552 break;
3553 }
3554 if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3555 Info = _WRONG_MESSAGE_FORMAT;
3556 break;
3557 }
3558 req = m_parms[0].info[0];
3559 plci->command = _MANUFACTURER_R;
3560 plci->m_command = command;
3561 plci->number = Number;
3562 if(req==CALL_REQ)
3563 {
3564 plci->b_channel = getChannel(&m_parms[1]);
3565 mixer_set_bchannel_id_esc (plci, plci->b_channel);
3566 if(plci->spoofed_msg==SPOOFING_REQUIRED)
3567 {
3568 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3569 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3570 plci->command = 0;
3571 break;
3572 }
3573 }
3574 else if(req==LAW_REQ)
3575 {
3576 plci->cr_enquiry = TRUE;
3577 }
3578 add_ss(plci,FTY,&m_parms[1]);
3579 sig_req(plci,req,0);
3580 send_req(plci);
3581 if(req==HANGUP)
3582 {
3583 if (plci->NL.Id && !plci->nl_remove_id)
3584 {
3585 if (plci->channels)
3586 {
3587 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3588 {
3589 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3590 {
3591 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3592 cleanup_ncci_data (plci, ncci);
3593 nl_req_ncci(plci,N_DISC,(byte)ncci);
3594 }
3595 }
3596 }
3597 mixer_remove (plci);
3598 nl_req_ncci(plci,REMOVE,0);
3599 send_req(plci);
3600 }
3601 }
3602 break;
3603
3604 case _DI_SIG_CTRL:
3605 /* signalling control for loop activation B-channel */
3606 if(!plci)
3607 {
3608 Info = _WRONG_IDENTIFIER;
3609 break;
3610 }
3611 if(m->length){
3612 plci->command = _MANUFACTURER_R;
3613 plci->number = Number;
3614 add_ss(plci,FTY,m);
3615 sig_req(plci,SIG_CTRL,0);
3616 send_req(plci);
3617 }
3618 else Info = _WRONG_MESSAGE_FORMAT;
3619 break;
3620
3621 case _DI_RXT_CTRL:
3622 /* activation control for receiver/transmitter B-channel */
3623 if(!plci)
3624 {
3625 Info = _WRONG_IDENTIFIER;
3626 break;
3627 }
3628 if(m->length){
3629 plci->command = _MANUFACTURER_R;
3630 plci->number = Number;
3631 add_ss(plci,FTY,m);
3632 sig_req(plci,DSP_CTRL,0);
3633 send_req(plci);
3634 }
3635 else Info = _WRONG_MESSAGE_FORMAT;
3636 break;
3637
3638 case _DI_ADV_CODEC:
3639 case _DI_DSP_CTRL:
3640 /* TEL_CTRL commands to support non standard adjustments: */
3641 /* Ring on/off, Handset micro volume, external micro vol. */
3642 /* handset+external speaker volume, receiver+transm. gain,*/
3643 /* handsfree on (hookinfo off), set mixer command */
3644
3645 if(command == _DI_ADV_CODEC)
3646 {
3647 if(!a->AdvCodecPLCI) {
3648 Info = _WRONG_STATE;
3649 break;
3650 }
3651 v_plci = a->AdvCodecPLCI;
3652 }
3653 else
3654 {
3655 if (plci
3656 && (m->length >= 3)
3657 && (m->info[1] == 0x1c)
3658 && (m->info[2] >= 1))
3659 {
3660 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3661 {
3662 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3663 {
3664 Info = _WRONG_STATE;
3665 break;
3666 }
3667 a->adv_voice_coef_length = m->info[2] - 1;
3668 if (a->adv_voice_coef_length > m->length - 3)
3669 a->adv_voice_coef_length = (byte)(m->length - 3);
3670 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3671 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3672 for (i = 0; i < a->adv_voice_coef_length; i++)
3673 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3674 if (plci->B1_facilities & B1_FACILITY_VOICE)
3675 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3676 break;
3677 }
3678 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3679 {
3680 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3681 {
3682 Info = _FACILITY_NOT_SUPPORTED;
3683 break;
3684 }
3685
3686 plci->dtmf_parameter_length = m->info[2] - 1;
3687 if (plci->dtmf_parameter_length > m->length - 3)
3688 plci->dtmf_parameter_length = (byte)(m->length - 3);
3689 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3690 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3691 for (i = 0; i < plci->dtmf_parameter_length; i++)
3692 plci->dtmf_parameter_buffer[i] = m->info[4+i];
3693 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3694 dtmf_parameter_write (plci);
3695 break;
3696
3697 }
3698 }
3699 v_plci = plci;
3700 }
3701
3702 if(!v_plci)
3703 {
3704 Info = _WRONG_IDENTIFIER;
3705 break;
3706 }
3707 if(m->length){
3708 add_ss(v_plci,FTY,m);
3709 sig_req(v_plci,TEL_CTRL,0);
3710 send_req(v_plci);
3711 }
3712 else Info = _WRONG_MESSAGE_FORMAT;
3713
3714 break;
3715
3716 case _DI_OPTIONS_REQUEST:
3717 if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3718 Info = _WRONG_MESSAGE_FORMAT;
3719 break;
3720 }
3721 if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3722 {
3723 Info = _FACILITY_NOT_SUPPORTED;
3724 break;
3725 }
3726 a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3727 break;
3728
3729
3730
3731 default:
3732 Info = _WRONG_MESSAGE_FORMAT;
3733 break;
3734 }
3735 }
3736
3737 sendf(appl,
3738 _MANUFACTURER_R|CONFIRM,
3739 Id,
3740 Number,
3741 "dww",_DI_MANU_ID,command,Info);
3742 return FALSE;
3743}
3744
3745
3746byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
3747{
3748 word indication;
3749
3750 API_PARSE m_parms[3];
3751 API_PARSE *ncpi;
3752 API_PARSE fax_parms[9];
3753 word i;
3754 byte len;
3755
3756
3757 dbug(1,dprintf("manufacturer_res"));
3758
3759 if ((msg[0].length == 0)
3760 || (msg[1].length == 0)
3761 || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3762 {
3763 return FALSE;
3764 }
3765 indication = GET_WORD(msg[1].info);
3766 switch (indication)
3767 {
3768
3769 case _DI_NEGOTIATE_B3:
3770 if(!plci)
3771 break;
3772 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3773 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3774 {
3775 dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3776 break;
3777 }
3778 if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3779 {
3780 dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3781 break;
3782 }
3783 ncpi = &m_parms[1];
3784 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3785 if (plci->fax_connect_info_length < len)
3786 {
3787 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3788 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3789 }
3790 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3791 {
3792 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3793 }
3794 else
3795 {
3796 if (plci->fax_connect_info_length <= len)
3797 plci->fax_connect_info_buffer[len] = 0;
3798 len += 1 + plci->fax_connect_info_buffer[len];
3799 if (plci->fax_connect_info_length <= len)
3800 plci->fax_connect_info_buffer[len] = 0;
3801 len += 1 + plci->fax_connect_info_buffer[len];
3802 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3803 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3804 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3805 for (i = 0; i < fax_parms[7].length; i++)
3806 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3807 }
3808 plci->fax_connect_info_length = len;
3809 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3810 start_internal_command (Id, plci, fax_edata_ack_command);
3811 break;
3812
3813 }
3814 return FALSE;
3815}
3816
3817/*------------------------------------------------------------------*/
3818/* IDI callback function */
3819/*------------------------------------------------------------------*/
3820
3821void callback(ENTITY * e)
3822{
3823 DIVA_CAPI_ADAPTER * a;
3824 APPL * appl;
3825 PLCI * plci;
3826 CAPI_MSG *m;
3827 word i, j;
3828 byte rc;
3829 byte ch;
3830 byte req;
3831 byte global_req;
3832 int no_cancel_rc;
3833
3834 dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3835 (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3836
3837 a = &(adapter[(byte)e->user[0]]);
3838 plci = &(a->plci[e->user[1]]);
3839 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3840
3841 /*
3842 If new protocol code and new XDI is used then CAPI should work
3843 fully in accordance with IDI cpec an look on callback field instead
3844 of Rc field for return codes.
3845 */
3846 if (((e->complete == 0xff) && no_cancel_rc) ||
3847 (e->Rc && !no_cancel_rc)) {
3848 rc = e->Rc;
3849 ch = e->RcCh;
3850 req = e->Req;
3851 e->Rc = 0;
3852
3853 if (e->user[0] & 0x8000)
3854 {
3855 /*
3856 If REMOVE request was sent then we have to wait until
3857 return code with Id set to zero arrives.
3858 All other return codes should be ignored.
3859 */
3860 if (req == REMOVE)
3861 {
3862 if (e->Id)
3863 {
3864 dbug(1,dprintf("cancel RC in REMOVE state"));
3865 return;
3866 }
3867 channel_flow_control_remove (plci);
3868 for (i = 0; i < 256; i++)
3869 {
3870 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3871 a->FlowControlIdTable[i] = 0;
3872 }
3873 plci->nl_remove_id = 0;
3874 if (plci->rx_dma_descriptor > 0) {
3875 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3876 plci->rx_dma_descriptor = 0;
3877 }
3878 }
3879 if (rc == OK_FC)
3880 {
3881 a->FlowControlIdTable[ch] = e->Id;
3882 a->FlowControlSkipTable[ch] = 0;
3883
3884 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3885 a->ch_flow_plci[ch] = plci->Id;
3886 plci->nl_req = 0;
3887 }
3888 else
3889 {
3890 /*
3891 Cancel return codes self, if feature was requested
3892 */
3893 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3894 a->FlowControlIdTable[ch] = 0;
3895 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3896 dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3897 return;
3898 }
3899 }
3900
3901 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3902 {
3903 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3904 if (ch == e->ReqCh)
3905 plci->nl_req = 0;
3906 }
3907 else
3908 plci->nl_req = 0;
3909 }
3910 if (plci->nl_req)
3911 control_rc (plci, 0, rc, ch, 0, TRUE);
3912 else
3913 {
3914 if (req == N_XON)
3915 {
3916 channel_x_on (plci, ch);
3917 if (plci->internal_command)
3918 control_rc (plci, req, rc, ch, 0, TRUE);
3919 }
3920 else
3921 {
3922 if (plci->nl_global_req)
3923 {
3924 global_req = plci->nl_global_req;
3925 plci->nl_global_req = 0;
3926 if (rc != ASSIGN_OK) {
3927 e->Id = 0;
3928 if (plci->rx_dma_descriptor > 0) {
3929 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3930 plci->rx_dma_descriptor = 0;
3931 }
3932 }
3933 channel_xmit_xon (plci);
3934 control_rc (plci, 0, rc, ch, global_req, TRUE);
3935 }
3936 else if (plci->data_sent)
3937 {
3938 channel_xmit_xon (plci);
3939 plci->data_sent = FALSE;
3940 plci->NL.XNum = 1;
3941 data_rc (plci, ch);
3942 if (plci->internal_command)
3943 control_rc (plci, req, rc, ch, 0, TRUE);
3944 }
3945 else
3946 {
3947 channel_xmit_xon (plci);
3948 control_rc (plci, req, rc, ch, 0, TRUE);
3949 }
3950 }
3951 }
3952 }
3953 else
3954 {
3955 /*
3956 If REMOVE request was sent then we have to wait until
3957 return code with Id set to zero arrives.
3958 All other return codes should be ignored.
3959 */
3960 if (req == REMOVE)
3961 {
3962 if (e->Id)
3963 {
3964 dbug(1,dprintf("cancel RC in REMOVE state"));
3965 return;
3966 }
3967 plci->sig_remove_id = 0;
3968 }
3969 plci->sig_req = 0;
3970 if (plci->sig_global_req)
3971 {
3972 global_req = plci->sig_global_req;
3973 plci->sig_global_req = 0;
3974 if (rc != ASSIGN_OK)
3975 e->Id = 0;
3976 channel_xmit_xon (plci);
3977 control_rc (plci, 0, rc, ch, global_req, FALSE);
3978 }
3979 else
3980 {
3981 channel_xmit_xon (plci);
3982 control_rc (plci, req, rc, ch, 0, FALSE);
3983 }
3984 }
3985 /*
3986 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3987 same callback. Also if new XDI and protocol code used then jump
3988 direct to finish.
3989 */
3990 if (no_cancel_rc) {
3991 channel_xmit_xon(plci);
3992 goto capi_callback_suffix;
3993 }
3994 }
3995
3996 channel_xmit_xon(plci);
3997
3998 if (e->Ind) {
3999 if (e->user[0] &0x8000) {
4000 byte Ind = e->Ind & 0x0f;
4001 byte Ch = e->IndCh;
4002 if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4003 (a->ch_flow_plci[Ch] == plci->Id)) {
4004 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4005 dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4006 }
4007 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4008 }
4009 nl_ind(plci);
4010 if ((e->RNR != 1) &&
4011 (a->ch_flow_plci[Ch] == plci->Id) &&
4012 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4013 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4014 dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4015 }
4016 } else {
4017 sig_ind(plci);
4018 }
4019 e->Ind = 0;
4020 }
4021
4022capi_callback_suffix:
4023
4024 while (!plci->req_in
4025 && !plci->internal_command
4026 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4027 {
4028 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4029
4030 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4031
4032 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4033 appl = *((APPL * *)(&((byte *)(plci->msg_in_queue))[j+i]));
4034 dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4035 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4036 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4037 {
4038 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4039 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4040 }
4041 else
4042 {
4043 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4044 }
4045 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4046 {
4047 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4048 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4049 }
4050 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4051 {
4052 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4053 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4054 }
4055 i = api_put (appl, m);
4056 if (i != 0)
4057 {
4058 if (m->header.command == _DATA_B3_R)
4059
4060 TransmitBufferFree (appl, (byte *)(m->info.data_b3_req.Data));
4061
4062 dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4063 break;
4064 }
4065
4066 if (plci->li_notify_update)
4067 {
4068 plci->li_notify_update = FALSE;
4069 mixer_notify_update (plci, FALSE);
4070 }
4071
4072 }
4073 send_data(plci);
4074 send_req(plci);
4075}
4076
4077
4078void control_rc(PLCI * plci, byte req, byte rc, byte ch, byte global_req, byte nl_rc)
4079{
4080 dword Id;
4081 dword rId;
4082 word Number;
4083 word Info=0;
4084 word i;
4085 word ncci;
4086 DIVA_CAPI_ADAPTER * a;
4087 APPL * appl;
4088 PLCI * rplci;
4089 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4090 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4091
4092 if (!plci) {
4093 dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4094 return;
4095 }
4096 dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4097 if(plci->req_in!=plci->req_out)
4098 {
4099 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4100 {
4101 dbug(1,dprintf("req_1return"));
4102 return;
4103 }
4104 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4105 }
4106 plci->req_in = plci->req_in_start = plci->req_out = 0;
4107 dbug(1,dprintf("control_rc"));
4108
4109 appl = plci->appl;
4110 a = plci->adapter;
4111 ncci = a->ch_ncci[ch];
4112 if(appl)
4113 {
4114 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4115 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4116 Number = plci->number;
4117 dbug(1,dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x",Id,plci->Id,plci->tel,plci->Sig.Id,plci->command,plci->internal_command));
4118 dbug(1,dprintf("channels=0x%x",plci->channels));
4119 if (plci_remove_check(plci))
4120 return;
4121 if(req==REMOVE && rc==ASSIGN_OK)
4122 {
4123 sig_req(plci,HANGUP,0);
4124 sig_req(plci,REMOVE,0);
4125 send_req(plci);
4126 }
4127 if(plci->command)
4128 {
4129 switch(plci->command)
4130 {
4131 case C_HOLD_REQ:
4132 dbug(1,dprintf("HoldRC=0x%x",rc));
4133 SSparms[1] = (byte)S_HOLD;
4134 if(rc!=OK)
4135 {
4136 plci->SuppState = IDLE;
4137 Info = 0x2001;
4138 }
4139 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4140 break;
4141
4142 case C_RETRIEVE_REQ:
4143 dbug(1,dprintf("RetrieveRC=0x%x",rc));
4144 SSparms[1] = (byte)S_RETRIEVE;
4145 if(rc!=OK)
4146 {
4147 plci->SuppState = CALL_HELD;
4148 Info = 0x2001;
4149 }
4150 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4151 break;
4152
4153 case _INFO_R:
4154 dbug(1,dprintf("InfoRC=0x%x",rc));
4155 if(rc!=OK) Info=_WRONG_STATE;
4156 sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4157 break;
4158
4159 case _CONNECT_R:
4160 dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4161 if (plci->State == INC_DIS_PENDING)
4162 break;
4163 if(plci->Sig.Id!=0xff)
4164 {
4165 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4166 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4167 {
4168 dbug(1,dprintf("No more IDs/Call_Req failed"));
4169 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4170 plci_remove(plci);
4171 plci->State = IDLE;
4172 break;
4173 }
4174 if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4175 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4176 }
4177 else /* D-ch activation */
4178 {
4179 if (rc != ASSIGN_OK)
4180 {
4181 dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4182 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4183 plci_remove(plci);
4184 plci->State = IDLE;
4185 break;
4186 }
4187 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4188 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4189 plci->State = INC_ACT_PENDING;
4190 }
4191 break;
4192
4193 case _CONNECT_I|RESPONSE:
4194 if (plci->State != INC_DIS_PENDING)
4195 plci->State = INC_CON_ACCEPT;
4196 break;
4197
4198 case _DISCONNECT_R:
4199 if (plci->State == INC_DIS_PENDING)
4200 break;
4201 if(plci->Sig.Id!=0xff)
4202 {
4203 plci->State = OUTG_DIS_PENDING;
4204 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4205 }
4206 break;
4207
4208 case SUSPEND_REQ:
4209 break;
4210
4211 case RESUME_REQ:
4212 break;
4213
4214 case _CONNECT_B3_R:
4215 if(rc!=OK)
4216 {
4217 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4218 break;
4219 }
4220 ncci = get_ncci (plci, ch, 0);
4221 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4222 plci->channels++;
4223 if(req==N_RESET)
4224 {
4225 a->ncci_state[ncci] = INC_ACT_PENDING;
4226 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4227 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4228 }
4229 else
4230 {
4231 a->ncci_state[ncci] = OUTG_CON_PENDING;
4232 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4233 }
4234 break;
4235
4236 case _CONNECT_B3_I|RESPONSE:
4237 break;
4238
4239 case _RESET_B3_R:
4240/* sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4241 break;
4242
4243 case _DISCONNECT_B3_R:
4244 sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4245 break;
4246
4247 case _MANUFACTURER_R:
4248 break;
4249
4250 case PERM_LIST_REQ:
4251 if(rc!=OK)
4252 {
4253 Info = _WRONG_IDENTIFIER;
4254 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4255 plci_remove(plci);
4256 }
4257 else
4258 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4259 break;
4260
4261 default:
4262 break;
4263 }
4264 plci->command = 0;
4265 }
4266 else if (plci->internal_command)
4267 {
4268 switch(plci->internal_command)
4269 {
4270 case BLOCK_PLCI:
4271 return;
4272
4273 case GET_MWI_STATE:
4274 if(rc==OK) /* command supported, wait for indication */
4275 {
4276 return;
4277 }
4278 plci_remove(plci);
4279 break;
4280
4281 /* Get Supported Services */
4282 case GETSERV_REQ_PEND:
4283 if(rc==OK) /* command supported, wait for indication */
4284 {
4285 break;
4286 }
4287 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4288 sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4289 plci_remove(plci);
4290 break;
4291
4292 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4293 case INTERR_NUMBERS_REQ_PEND:
4294 case CF_START_PEND: /* Call Forwarding Start pending */
4295 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4296 case CCBS_REQUEST_REQ_PEND:
4297 case CCBS_DEACTIVATE_REQ_PEND:
4298 case CCBS_INTERROGATE_REQ_PEND:
4299 switch(plci->internal_command)
4300 {
4301 case INTERR_DIVERSION_REQ_PEND:
4302 SSparms[1] = S_INTERROGATE_DIVERSION;
4303 break;
4304 case INTERR_NUMBERS_REQ_PEND:
4305 SSparms[1] = S_INTERROGATE_NUMBERS;
4306 break;
4307 case CF_START_PEND:
4308 SSparms[1] = S_CALL_FORWARDING_START;
4309 break;
4310 case CF_STOP_PEND:
4311 SSparms[1] = S_CALL_FORWARDING_STOP;
4312 break;
4313 case CCBS_REQUEST_REQ_PEND:
4314 SSparms[1] = S_CCBS_REQUEST;
4315 break;
4316 case CCBS_DEACTIVATE_REQ_PEND:
4317 SSparms[1] = S_CCBS_DEACTIVATE;
4318 break;
4319 case CCBS_INTERROGATE_REQ_PEND:
4320 SSparms[1] = S_CCBS_INTERROGATE;
4321 break;
4322 }
4323 if(global_req==ASSIGN)
4324 {
4325 dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4326 return;
4327 }
4328 if(!plci->appl) break;
4329 if(rc==ISDN_GUARD_REJ)
4330 {
4331 Info = _CAPI_GUARD_ERROR;
4332 }
4333 else if(rc!=OK)
4334 {
4335 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4336 }
4337 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4338 plci->number,"wws",Info,(word)3,SSparms);
4339 if(Info) plci_remove(plci);
4340 break;
4341
4342 /* 3pty conference pending */
4343 case PTY_REQ_PEND:
4344 if(!plci->relatedPTYPLCI) break;
4345 rplci = plci->relatedPTYPLCI;
4346 SSparms[1] = plci->ptyState;
4347 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4348 if(rplci->tel) rId|=EXT_CONTROLLER;
4349 if(rc!=OK)
4350 {
4351 Info = 0x300E; /* not supported */
4352 plci->relatedPTYPLCI = NULL;
4353 plci->ptyState = 0;
4354 }
4355 sendf(rplci->appl,
4356 _FACILITY_R|CONFIRM,
4357 rId,
4358 plci->number,
4359 "wws",Info,(word)3,SSparms);
4360 break;
4361
4362 /* Explicit Call Transfer pending */
4363 case ECT_REQ_PEND:
4364 dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4365 if(!plci->relatedPTYPLCI) break;
4366 rplci = plci->relatedPTYPLCI;
4367 SSparms[1] = S_ECT;
4368 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4369 if(rplci->tel) rId|=EXT_CONTROLLER;
4370 if(rc!=OK)
4371 {
4372 Info = 0x300E; /* not supported */
4373 plci->relatedPTYPLCI = NULL;
4374 plci->ptyState = 0;
4375 }
4376 sendf(rplci->appl,
4377 _FACILITY_R|CONFIRM,
4378 rId,
4379 plci->number,
4380 "wws",Info,(word)3,SSparms);
4381 break;
4382
4383 case _MANUFACTURER_R:
4384 dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4385 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4386 {
4387 dbug(1,dprintf("No more IDs"));
4388 sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4389 plci_remove(plci); /* after codec init, internal codec commands pending */
4390 }
4391 break;
4392
4393 case _CONNECT_R:
4394 dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4395 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4396 {
4397 dbug(1,dprintf("No more IDs"));
4398 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4399 plci_remove(plci); /* after codec init, internal codec commands pending */
4400 }
4401 break;
4402
4403 case PERM_COD_HOOK: /* finished with Hook_Ind */
4404 return;
4405
4406 case PERM_COD_CALL:
4407 dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4408 plci->internal_command = PERM_COD_CONN_PEND;
4409 return;
4410
4411 case PERM_COD_ASSIGN:
4412 dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4413 if(rc!=ASSIGN_OK) break;
4414 sig_req(plci,CALL_REQ,0);
4415 send_req(plci);
4416 plci->internal_command = PERM_COD_CALL;
4417 return;
4418
4419 /* Null Call Reference Request pending */
4420 case C_NCR_FAC_REQ:
4421 dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4422 if(global_req==ASSIGN)
4423 {
4424 if(rc==ASSIGN_OK)
4425 {
4426 return;
4427 }
4428 else
4429 {
4430 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4431 appl->NullCREnable = FALSE;
4432 plci_remove(plci);
4433 }
4434 }
4435 else if(req==NCR_FACILITY)
4436 {
4437 if(rc==OK)
4438 {
4439 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4440 }
4441 else
4442 {
4443 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4444 appl->NullCREnable = FALSE;
4445 }
4446 plci_remove(plci);
4447 }
4448 break;
4449
4450 case HOOK_ON_REQ:
4451 if(plci->channels)
4452 {
4453 if(a->ncci_state[ncci]==CONNECTED)
4454 {
4455 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4456 cleanup_ncci_data (plci, ncci);
4457 nl_req_ncci(plci,N_DISC,(byte)ncci);
4458 }
4459 break;
4460 }
4461 break;
4462
4463 case HOOK_OFF_REQ:
4464 if (plci->State == INC_DIS_PENDING)
4465 break;
4466 sig_req(plci,CALL_REQ,0);
4467 send_req(plci);
4468 plci->State=OUTG_CON_PENDING;
4469 break;
4470
4471
4472 case MWI_ACTIVATE_REQ_PEND:
4473 case MWI_DEACTIVATE_REQ_PEND:
4474 if(global_req == ASSIGN && rc==ASSIGN_OK)
4475 {
4476 dbug(1,dprintf("MWI_REQ assigned"));
4477 return;
4478 }
4479 else if(rc!=OK)
4480 {
4481 if(rc==WRONG_IE)
4482 {
4483 Info = 0x2007; /* Illegal message parameter coding */
4484 dbug(1,dprintf("MWI_REQ invalid parameter"));
4485 }
4486 else
4487 {
4488 Info = 0x300B; /* not supported */
4489 dbug(1,dprintf("MWI_REQ not supported"));
4490 }
4491 /* 0x3010: Request not allowed in this state */
4492 PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4493
4494 }
4495 if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4496 {
4497 PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4498 }
4499 else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4500
4501 if(plci->cr_enquiry)
4502 {
4503 sendf(plci->appl,
4504 _FACILITY_R|CONFIRM,
4505 Id&0xf,
4506 plci->number,
4507 "wws",Info,(word)3,SSparms);
4508 if(rc!=OK) plci_remove(plci);
4509 }
4510 else
4511 {
4512 sendf(plci->appl,
4513 _FACILITY_R|CONFIRM,
4514 Id,
4515 plci->number,
4516 "wws",Info,(word)3,SSparms);
4517 }
4518 break;
4519
4520 case CONF_BEGIN_REQ_PEND:
4521 case CONF_ADD_REQ_PEND:
4522 case CONF_SPLIT_REQ_PEND:
4523 case CONF_DROP_REQ_PEND:
4524 case CONF_ISOLATE_REQ_PEND:
4525 case CONF_REATTACH_REQ_PEND:
4526 dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4527 if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4528 rplci = plci;
4529 rId = Id;
4530 switch(plci->internal_command)
4531 {
4532 case CONF_BEGIN_REQ_PEND:
4533 SSparms[1] = S_CONF_BEGIN;
4534 break;
4535 case CONF_ADD_REQ_PEND:
4536 SSparms[1] = S_CONF_ADD;
4537 rplci = plci->relatedPTYPLCI;
4538 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4539 break;
4540 case CONF_SPLIT_REQ_PEND:
4541 SSparms[1] = S_CONF_SPLIT;
4542 break;
4543 case CONF_DROP_REQ_PEND:
4544 SSparms[1] = S_CONF_DROP;
4545 break;
4546 case CONF_ISOLATE_REQ_PEND:
4547 SSparms[1] = S_CONF_ISOLATE;
4548 break;
4549 case CONF_REATTACH_REQ_PEND:
4550 SSparms[1] = S_CONF_REATTACH;
4551 break;
4552 }
4553
4554 if(rc!=OK)
4555 {
4556 Info = 0x300E; /* not supported */
4557 plci->relatedPTYPLCI = NULL;
4558 plci->ptyState = 0;
4559 }
4560 sendf(rplci->appl,
4561 _FACILITY_R|CONFIRM,
4562 rId,
4563 plci->number,
4564 "wws",Info,(word)3,SSparms);
4565 break;
4566
4567 case VSWITCH_REQ_PEND:
4568 if(rc!=OK)
4569 {
4570 if(plci->relatedPTYPLCI)
4571 {
4572 plci->relatedPTYPLCI->vswitchstate=0;
4573 plci->relatedPTYPLCI->vsprot=0;
4574 plci->relatedPTYPLCI->vsprotdialect=0;
4575 }
4576 plci->vswitchstate=0;
4577 plci->vsprot=0;
4578 plci->vsprotdialect=0;
4579 }
4580 else
4581 {
4582 if(plci->relatedPTYPLCI &&
4583 plci->vswitchstate==1 &&
4584 plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4585 plci->vswitchstate=3;
4586 }
4587 break;
4588
4589 /* Call Deflection Request pending (SSCT) */
4590 case CD_REQ_PEND:
4591 SSparms[1] = S_CALL_DEFLECTION;
4592 if(rc!=OK)
4593 {
4594 Info = 0x300E; /* not supported */
4595 plci->appl->CDEnable = 0;
4596 }
4597 sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4598 plci->number,"wws",Info,(word)3,SSparms);
4599 break;
4600
4601 case RTP_CONNECT_B3_REQ_COMMAND_2:
4602 if (rc == OK)
4603 {
4604 ncci = get_ncci (plci, ch, 0);
4605 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4606 plci->channels++;
4607 a->ncci_state[ncci] = OUTG_CON_PENDING;
4608 }
4609
4610 default:
4611 if (plci->internal_command_queue[0])
4612 {
4613 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4614 if (plci->internal_command)
4615 return;
4616 }
4617 break;
4618 }
4619 next_internal_command (Id, plci);
4620 }
4621 }
4622 else /* appl==0 */
4623 {
4624 Id = ((word)plci->Id<<8)|plci->adapter->Id;
4625 if(plci->tel) Id|=EXT_CONTROLLER;
4626
4627 switch(plci->internal_command)
4628 {
4629 case BLOCK_PLCI:
4630 return;
4631
4632 case START_L1_SIG_ASSIGN_PEND:
4633 case REM_L1_SIG_ASSIGN_PEND:
4634 if(global_req == ASSIGN)
4635 {
4636 break;
4637 }
4638 else
4639 {
4640 dbug(1,dprintf("***L1 Req rem PLCI"));
4641 plci->internal_command = 0;
4642 sig_req(plci,REMOVE,0);
4643 send_req(plci);
4644 }
4645 break;
4646
4647 /* Call Deflection Request pending, just no appl ptr assigned */
4648 case CD_REQ_PEND:
4649 SSparms[1] = S_CALL_DEFLECTION;
4650 if(rc!=OK)
4651 {
4652 Info = 0x300E; /* not supported */
4653 }
4654 for(i=0; i<max_appl; i++)
4655 {
4656 if(application[i].CDEnable)
4657 {
4658 if(!application[i].Id) application[i].CDEnable = 0;
4659 else
4660 {
4661 sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4662 plci->number,"wws",Info,(word)3,SSparms);
4663 if(Info) application[i].CDEnable = 0;
4664 }
4665 }
4666 }
4667 plci->internal_command = 0;
4668 break;
4669
4670 case PERM_COD_HOOK: /* finished with Hook_Ind */
4671 return;
4672
4673 case PERM_COD_CALL:
4674 plci->internal_command = PERM_COD_CONN_PEND;
4675 dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4676 return;
4677
4678 case PERM_COD_ASSIGN:
4679 dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4680 plci->internal_command = 0;
4681 if(rc!=ASSIGN_OK) break;
4682 plci->internal_command = PERM_COD_CALL;
4683 sig_req(plci,CALL_REQ,0);
4684 send_req(plci);
4685 return;
4686
4687 case LISTEN_SIG_ASSIGN_PEND:
4688 if(rc == ASSIGN_OK)
4689 {
4690 plci->internal_command = 0;
4691 dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4692 add_p(plci,ESC,"\x02\x18\x00"); /* support call waiting */
4693 sig_req(plci,INDICATE_REQ,0);
4694 send_req(plci);
4695 }
4696 else
4697 {
4698 dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4699 a->listen_active--;
4700 plci_remove(plci);
4701 plci->State = IDLE;
4702 }
4703 break;
4704
4705 case USELAW_REQ:
4706 if(global_req == ASSIGN)
4707 {
4708 if (rc==ASSIGN_OK)
4709 {
4710 sig_req(plci,LAW_REQ,0);
4711 send_req(plci);
4712 dbug(1,dprintf("Auto-Law assigned"));
4713 }
4714 else
4715 {
4716 dbug(1,dprintf("Auto-Law assign failed"));
4717 a->automatic_law = 3;
4718 plci->internal_command = 0;
4719 a->automatic_lawPLCI = NULL;
4720 }
4721 break;
4722 }
4723 else if(req == LAW_REQ && rc==OK)
4724 {
4725 dbug(1,dprintf("Auto-Law initiated"));
4726 a->automatic_law = 2;
4727 plci->internal_command = 0;
4728 }
4729 else
4730 {
4731 dbug(1,dprintf("Auto-Law not supported"));
4732 a->automatic_law = 3;
4733 plci->internal_command = 0;
4734 sig_req(plci,REMOVE,0);
4735 send_req(plci);
4736 a->automatic_lawPLCI = NULL;
4737 }
4738 break;
4739 }
4740 plci_remove_check(plci);
4741 }
4742}
4743
4744void data_rc(PLCI * plci, byte ch)
4745{
4746 dword Id;
4747 DIVA_CAPI_ADAPTER * a;
4748 NCCI *ncci_ptr;
4749 DATA_B3_DESC *data;
4750 word ncci;
4751
4752 if (plci->appl)
4753 {
4754 TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4755 a = plci->adapter;
4756 ncci = a->ch_ncci[ch];
4757 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4758 {
4759 ncci_ptr = &(a->ncci[ncci]);
4760 dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4761 if (ncci_ptr->data_pending)
4762 {
4763 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4764 if (!(data->Flags &4) && a->ncci_state[ncci])
4765 {
4766 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4767 if(plci->tel) Id|=EXT_CONTROLLER;
4768 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4769 "ww",data->Handle,0);
4770 }
4771 (ncci_ptr->data_out)++;
4772 if (ncci_ptr->data_out == MAX_DATA_B3)
4773 ncci_ptr->data_out = 0;
4774 (ncci_ptr->data_pending)--;
4775 }
4776 }
4777 }
4778}
4779
4780void data_ack(PLCI * plci, byte ch)
4781{
4782 dword Id;
4783 DIVA_CAPI_ADAPTER * a;
4784 NCCI *ncci_ptr;
4785 word ncci;
4786
4787 a = plci->adapter;
4788 ncci = a->ch_ncci[ch];
4789 ncci_ptr = &(a->ncci[ncci]);
4790 if (ncci_ptr->data_ack_pending)
4791 {
4792 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4793 {
4794 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4795 if(plci->tel) Id|=EXT_CONTROLLER;
4796 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4797 "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4798 }
4799 (ncci_ptr->data_ack_out)++;
4800 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4801 ncci_ptr->data_ack_out = 0;
4802 (ncci_ptr->data_ack_pending)--;
4803 }
4804}
4805
4806void sig_ind(PLCI * plci)
4807{
4808 dword x_Id;
4809 dword Id;
4810 dword rId;
4811 word Number = 0;
4812 word i;
4813 word cip;
4814 dword cip_mask;
4815 byte *ie;
4816 DIVA_CAPI_ADAPTER * a;
4817 API_PARSE saved_parms[MAX_MSG_PARMS+1];
4818#define MAXPARMSIDS 31
4819 byte * parms[MAXPARMSIDS];
4820 byte * add_i[4];
4821 byte * multi_fac_parms[MAX_MULTI_IE];
4822 byte * multi_pi_parms [MAX_MULTI_IE];
4823 byte * multi_ssext_parms [MAX_MULTI_IE];
4824 byte * multi_CiPN_parms [MAX_MULTI_IE];
4825
4826 byte * multi_vswitch_parms [MAX_MULTI_IE];
4827
4828 byte ai_len;
4829 byte *esc_chi = "";
4830 byte *esc_law = "";
4831 byte *pty_cai = "";
4832 byte *esc_cr = "";
4833 byte *esc_profile = "";
4834
4835 byte facility[256];
4836 PLCI * tplci = NULL;
4837 byte chi[] = "\x02\x18\x01";
4838 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4839 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4840 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4841 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4842 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4843 /* (see Info_Mask Bit 4, first IE. then the message type) */
4844 word parms_id[] =
4845 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4846 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4847 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4848 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4849 /* 14 FTY repl by ESC_CHI */
4850 /* 18 PI repl by ESC_LAW */
4851 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4852 word multi_fac_id[] = {1, FTY};
4853 word multi_pi_id[] = {1, PI};
4854 word multi_CiPN_id[] = {1, OAD};
4855 word multi_ssext_id[] = {1, ESC_SSEXT};
4856
4857 word multi_vswitch_id[] = {1, ESC_VSWITCH};
4858
4859 byte * cau;
4860 word ncci;
4861 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4862 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4863 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4864 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4865 byte force_mt_info = FALSE;
4866 byte dir;
4867 dword d;
4868 word w;
4869
4870 a = plci->adapter;
4871 Id = ((word)plci->Id<<8)|a->Id;
4872 PUT_WORD(&SS_Ind[4],0x0000);
4873
4874 if (plci->sig_remove_id)
4875 {
4876 plci->Sig.RNR = 2; /* discard */
4877 dbug(1,dprintf("SIG discard while remove pending"));
4878 return;
4879 }
4880 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4881 dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4882 Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4883 if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4884 {
4885 plci->Sig.RNR = 1;
4886 return;
4887 }
4888 if(plci->Sig.Ind==HANGUP && plci->channels)
4889 {
4890 plci->Sig.RNR = 1;
4891 plci->hangup_flow_ctrl_timer++;
4892 /* recover the network layer after timeout */
4893 if(plci->hangup_flow_ctrl_timer==100)
4894 {
4895 dbug(1,dprintf("Exceptional disc"));
4896 plci->Sig.RNR = 0;
4897 plci->hangup_flow_ctrl_timer = 0;
4898 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4899 {
4900 if (a->ncci_plci[ncci] == plci->Id)
4901 {
4902 cleanup_ncci_data (plci, ncci);
4903 if(plci->channels)plci->channels--;
4904 if (plci->appl)
4905 sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4906 }
4907 }
4908 if (plci->appl)
4909 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4910 plci_remove(plci);
4911 plci->State=IDLE;
4912 }
4913 return;
4914 }
4915
4916 /* do first parse the info with no OAD in, because OAD will be converted */
4917 /* first the multiple facility IE, then mult. progress ind. */
4918 /* then the parameters for the info_ind + conn_ind */
4919 IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4920 IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4921 IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4922
4923 IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4924
4925 IndParse(plci,parms_id,parms,0);
4926 IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4927 esc_chi = parms[14];
4928 esc_law = parms[18];
4929 pty_cai = parms[24];
4930 esc_cr = parms[25];
4931 esc_profile = parms[27];
4932 if(esc_cr[0] && plci)
4933 {
4934 if(plci->cr_enquiry && plci->appl)
4935 {
4936 plci->cr_enquiry = FALSE;
4937 /* d = MANU_ID */
4938 /* w = m_command */
4939 /* b = total length */
4940 /* b = indication type */
4941 /* b = length of all IEs */
4942 /* b = IE1 */
4943 /* S = IE1 length + cont. */
4944 /* b = IE2 */
4945 /* S = IE2 lenght + cont. */
4946 sendf(plci->appl,
4947 _MANUFACTURER_I,
4948 Id,
4949 0,
4950 "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4951 2+1+1+esc_cr[0]+1+1+esc_law[0],plci->Sig.Ind,1+1+esc_cr[0]+1+1+esc_law[0],ESC,esc_cr,ESC,esc_law);
4952 }
4953 }
4954 /* create the additional info structure */
4955 add_i[1] = parms[15]; /* KEY of additional info */
4956 add_i[2] = parms[11]; /* UUI of additional info */
4957 ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4958
4959 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4960 /* indication returns by the card if requested by the function */
4961 /* AutomaticLaw() after driver init */
4962 if (a->automatic_law<4)
4963 {
4964 if(esc_law[0]){
4965 if(esc_law[2]){
4966 dbug(0,dprintf("u-Law selected"));
4967 a->u_law = 1;
4968 }
4969 else {
4970 dbug(0,dprintf("a-Law selected"));
4971 a->u_law = 0;
4972 }
4973 a->automatic_law = 4;
4974 if(plci==a->automatic_lawPLCI) {
4975 plci->internal_command = 0;
4976 sig_req(plci,REMOVE,0);
4977 send_req(plci);
4978 a->automatic_lawPLCI = NULL;
4979 }
4980 }
4981 if (esc_profile[0])
4982 {
4983 dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4984 UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
4985 GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
4986 GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
4987
4988 a->profile.Global_Options &= 0x000000ffL;
4989 a->profile.B1_Protocols &= 0x000003ffL;
4990 a->profile.B2_Protocols &= 0x00001fdfL;
4991 a->profile.B3_Protocols &= 0x000000b7L;
4992
4993 a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
4994 GL_BCHANNEL_OPERATION_SUPPORTED;
4995 a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
4996 a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
4997 a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
4998 a->manufacturer_features = GET_DWORD (&esc_profile[46]);
4999 a->man_profile.private_options = 0;
5000
5001 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5002 {
5003 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5004 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5005 }
5006
5007
5008 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5009 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5010 a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5011 a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5012
5013
5014 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5015 a->man_profile.private_options |= 1L << PRIVATE_T38;
5016
5017
5018 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5019 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5020
5021
5022 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5023 a->man_profile.private_options |= 1L << PRIVATE_V18;
5024
5025
5026 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5027 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5028
5029
5030 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5031 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5032
5033
5034 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5035 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5036
5037
5038 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5039 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5040
5041
5042 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5043 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5044
5045 }
5046 else
5047 {
5048 a->profile.Global_Options &= 0x0000007fL;
5049 a->profile.B1_Protocols &= 0x000003dfL;
5050 a->profile.B2_Protocols &= 0x00001adfL;
5051 a->profile.B3_Protocols &= 0x000000b7L;
5052 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5053 }
5054 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5055 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5056 {
5057 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5058 }
5059 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5060 dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5061 UnMapController (a->Id), a->profile.Global_Options,
5062 a->profile.B1_Protocols, a->profile.B2_Protocols,
5063 a->profile.B3_Protocols, a->manufacturer_features));
5064 }
5065 /* codec plci for the handset/hook state support is just an internal id */
5066 if(plci!=a->AdvCodecPLCI)
5067 {
5068 force_mt_info = SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5069 force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5070 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5071 SendInfo(plci,Id, parms, force_mt_info);
5072
5073 VSwitchReqInd(plci,Id,multi_vswitch_parms);
5074
5075 }
5076
5077 /* switch the codec to the b-channel */
5078 if(esc_chi[0] && plci && !plci->SuppState){
5079 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5080 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5081 dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5082 if(plci->tel==ADV_VOICE && plci->appl) {
5083 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5084 }
5085 }
5086
5087 if(plci->appl) Number = plci->appl->Number++;
5088
5089 switch(plci->Sig.Ind) {
5090 /* Response to Get_Supported_Services request */
5091 case S_SUPPORTED:
5092 dbug(1,dprintf("S_Supported"));
5093 if(!plci->appl) break;
5094 if(pty_cai[0]==4)
5095 {
5096 PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5097 }
5098 else
5099 {
5100 PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5101 }
5102 PUT_WORD (&CF_Ind[1], 0);
5103 PUT_WORD (&CF_Ind[4], 0);
5104 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5105 plci_remove(plci);
5106 break;
5107
5108 /* Supplementary Service rejected */
5109 case S_SERVICE_REJ:
5110 dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5111 if(!pty_cai[0]) break;
5112 switch (pty_cai[5])
5113 {
5114 case ECT_EXECUTE:
5115 case THREE_PTY_END:
5116 case THREE_PTY_BEGIN:
5117 if(!plci->relatedPTYPLCI) break;
5118 tplci = plci->relatedPTYPLCI;
5119 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5120 if(tplci->tel) rId|=EXT_CONTROLLER;
5121 if(pty_cai[5]==ECT_EXECUTE)
5122 {
5123 PUT_WORD(&SS_Ind[1],S_ECT);
5124
5125 plci->vswitchstate=0;
5126 plci->relatedPTYPLCI->vswitchstate=0;
5127
5128 }
5129 else
5130 {
5131 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5132 }
5133 if(pty_cai[2]!=0xff)
5134 {
5135 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5136 }
5137 else
5138 {
5139 PUT_WORD(&SS_Ind[4],0x300E);
5140 }
5141 plci->relatedPTYPLCI = NULL;
5142 plci->ptyState = 0;
5143 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5144 break;
5145
5146 case CALL_DEFLECTION:
5147 if(pty_cai[2]!=0xff)
5148 {
5149 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5150 }
5151 else
5152 {
5153 PUT_WORD(&SS_Ind[4],0x300E);
5154 }
5155 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5156 for(i=0; i<max_appl; i++)
5157 {
5158 if(application[i].CDEnable)
5159 {
5160 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5161 application[i].CDEnable = FALSE;
5162 }
5163 }
5164 break;
5165
5166 case DEACTIVATION_DIVERSION:
5167 case ACTIVATION_DIVERSION:
5168 case DIVERSION_INTERROGATE_CFU:
5169 case DIVERSION_INTERROGATE_CFB:
5170 case DIVERSION_INTERROGATE_CFNR:
5171 case DIVERSION_INTERROGATE_NUM:
5172 case CCBS_REQUEST:
5173 case CCBS_DEACTIVATE:
5174 case CCBS_INTERROGATE:
5175 if(!plci->appl) break;
5176 if(pty_cai[2]!=0xff)
5177 {
5178 PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5179 }
5180 else
5181 {
5182 PUT_WORD(&Interr_Err_Ind[4],0x300E);
5183 }
5184 switch (pty_cai[5])
5185 {
5186 case DEACTIVATION_DIVERSION:
5187 dbug(1,dprintf("Deact_Div"));
5188 Interr_Err_Ind[0]=0x9;
5189 Interr_Err_Ind[3]=0x6;
5190 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5191 break;
5192 case ACTIVATION_DIVERSION:
5193 dbug(1,dprintf("Act_Div"));
5194 Interr_Err_Ind[0]=0x9;
5195 Interr_Err_Ind[3]=0x6;
5196 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5197 break;
5198 case DIVERSION_INTERROGATE_CFU:
5199 case DIVERSION_INTERROGATE_CFB:
5200 case DIVERSION_INTERROGATE_CFNR:
5201 dbug(1,dprintf("Interr_Div"));
5202 Interr_Err_Ind[0]=0xa;
5203 Interr_Err_Ind[3]=0x7;
5204 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5205 break;
5206 case DIVERSION_INTERROGATE_NUM:
5207 dbug(1,dprintf("Interr_Num"));
5208 Interr_Err_Ind[0]=0xa;
5209 Interr_Err_Ind[3]=0x7;
5210 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5211 break;
5212 case CCBS_REQUEST:
5213 dbug(1,dprintf("CCBS Request"));
5214 Interr_Err_Ind[0]=0xd;
5215 Interr_Err_Ind[3]=0xa;
5216 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5217 break;
5218 case CCBS_DEACTIVATE:
5219 dbug(1,dprintf("CCBS Deactivate"));
5220 Interr_Err_Ind[0]=0x9;
5221 Interr_Err_Ind[3]=0x6;
5222 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5223 break;
5224 case CCBS_INTERROGATE:
5225 dbug(1,dprintf("CCBS Interrogate"));
5226 Interr_Err_Ind[0]=0xb;
5227 Interr_Err_Ind[3]=0x8;
5228 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5229 break;
5230 }
5231 PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5232 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5233 plci_remove(plci);
5234 break;
5235 case ACTIVATION_MWI:
5236 case DEACTIVATION_MWI:
5237 if(pty_cai[5]==ACTIVATION_MWI)
5238 {
5239 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5240 }
5241 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5242
5243 if(pty_cai[2]!=0xff)
5244 {
5245 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5246 }
5247 else
5248 {
5249 PUT_WORD(&SS_Ind[4],0x300E);
5250 }
5251
5252 if(plci->cr_enquiry)
5253 {
5254 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5255 plci_remove(plci);
5256 }
5257 else
5258 {
5259 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5260 }
5261 break;
5262 case CONF_ADD: /* ERROR */
5263 case CONF_BEGIN:
5264 case CONF_DROP:
5265 case CONF_ISOLATE:
5266 case CONF_REATTACH:
5267 CONF_Ind[0]=9;
5268 CONF_Ind[3]=6;
5269 switch(pty_cai[5])
5270 {
5271 case CONF_BEGIN:
5272 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5273 plci->ptyState = 0;
5274 break;
5275 case CONF_DROP:
5276 CONF_Ind[0]=5;
5277 CONF_Ind[3]=2;
5278 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5279 plci->ptyState = CONNECTED;
5280 break;
5281 case CONF_ISOLATE:
5282 CONF_Ind[0]=5;
5283 CONF_Ind[3]=2;
5284 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5285 plci->ptyState = CONNECTED;
5286 break;
5287 case CONF_REATTACH:
5288 CONF_Ind[0]=5;
5289 CONF_Ind[3]=2;
5290 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5291 plci->ptyState = CONNECTED;
5292 break;
5293 case CONF_ADD:
5294 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5295 plci->relatedPTYPLCI = NULL;
5296 tplci=plci->relatedPTYPLCI;
5297 if(tplci) tplci->ptyState = CONNECTED;
5298 plci->ptyState = CONNECTED;
5299 break;
5300 }
5301
5302 if(pty_cai[2]!=0xff)
5303 {
5304 PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5305 }
5306 else
5307 {
5308 PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5309 within the required time */
5310 }
5311
5312 PUT_DWORD(&CONF_Ind[6],0x0);
5313 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5314 break;
5315 }
5316 break;
5317
5318 /* Supplementary Service indicates success */
5319 case S_SERVICE:
5320 dbug(1,dprintf("Service_Ind"));
5321 PUT_WORD (&CF_Ind[4], 0);
5322 switch (pty_cai[5])
5323 {
5324 case THREE_PTY_END:
5325 case THREE_PTY_BEGIN:
5326 case ECT_EXECUTE:
5327 if(!plci->relatedPTYPLCI) break;
5328 tplci = plci->relatedPTYPLCI;
5329 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5330 if(tplci->tel) rId|=EXT_CONTROLLER;
5331 if(pty_cai[5]==ECT_EXECUTE)
5332 {
5333 PUT_WORD(&SS_Ind[1],S_ECT);
5334
5335 if(plci->vswitchstate!=3)
5336 {
5337
5338 plci->ptyState = IDLE;
5339 plci->relatedPTYPLCI = NULL;
5340 plci->ptyState = 0;
5341
5342 }
5343
5344 dbug(1,dprintf("ECT OK"));
5345 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5346
5347
5348
5349 }
5350 else
5351 {
5352 switch (plci->ptyState)
5353 {
5354 case S_3PTY_BEGIN:
5355 plci->ptyState = CONNECTED;
5356 dbug(1,dprintf("3PTY ON"));
5357 break;
5358
5359 case S_3PTY_END:
5360 plci->ptyState = IDLE;
5361 plci->relatedPTYPLCI = NULL;
5362 plci->ptyState = 0;
5363 dbug(1,dprintf("3PTY OFF"));
5364 break;
5365 }
5366 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5367 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5368 }
5369 break;
5370
5371 case CALL_DEFLECTION:
5372 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5373 for(i=0; i<max_appl; i++)
5374 {
5375 if(application[i].CDEnable)
5376 {
5377 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5378 application[i].CDEnable = FALSE;
5379 }
5380 }
5381 break;
5382
5383 case DEACTIVATION_DIVERSION:
5384 case ACTIVATION_DIVERSION:
5385 if(!plci->appl) break;
5386 PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5387 PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5388 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5389 plci_remove(plci);
5390 break;
5391
5392 case DIVERSION_INTERROGATE_CFU:
5393 case DIVERSION_INTERROGATE_CFB:
5394 case DIVERSION_INTERROGATE_CFNR:
5395 case DIVERSION_INTERROGATE_NUM:
5396 case CCBS_REQUEST:
5397 case CCBS_DEACTIVATE:
5398 case CCBS_INTERROGATE:
5399 if(!plci->appl) break;
5400 switch (pty_cai[5])
5401 {
5402 case DIVERSION_INTERROGATE_CFU:
5403 case DIVERSION_INTERROGATE_CFB:
5404 case DIVERSION_INTERROGATE_CFNR:
5405 dbug(1,dprintf("Interr_Div"));
5406 PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5407 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5408 break;
5409 case DIVERSION_INTERROGATE_NUM:
5410 dbug(1,dprintf("Interr_Num"));
5411 PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5412 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5413 break;
5414 case CCBS_REQUEST:
5415 dbug(1,dprintf("CCBS Request"));
5416 PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5417 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5418 break;
5419 case CCBS_DEACTIVATE:
5420 dbug(1,dprintf("CCBS Deactivate"));
5421 PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5422 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5423 break;
5424 case CCBS_INTERROGATE:
5425 dbug(1,dprintf("CCBS Interrogate"));
5426 PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5427 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5428 break;
5429 }
5430 PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5431 PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5432 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5433 plci_remove(plci);
5434 break;
5435
5436 case ACTIVATION_MWI:
5437 case DEACTIVATION_MWI:
5438 if(pty_cai[5]==ACTIVATION_MWI)
5439 {
5440 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5441 }
5442 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5443 if(plci->cr_enquiry)
5444 {
5445 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5446 plci_remove(plci);
5447 }
5448 else
5449 {
5450 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5451 }
5452 break;
5453 case MWI_INDICATION:
5454 if(pty_cai[0]>=0x12)
5455 {
5456 PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5457 pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5458 pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5459 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5460 {
5461 if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5462 {
5463 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5464 plci_remove(plci);
5465 return;
5466 }
5467 else sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5468 pty_cai[0]=0;
5469 }
5470 else
5471 {
5472 for(i=0; i<max_appl; i++)
5473 {
5474 if(a->Notification_Mask[i]&SMASK_MWI)
5475 {
5476 sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5477 pty_cai[0]=0;
5478 }
5479 }
5480 }
5481
5482 if(!pty_cai[0])
5483 { /* acknowledge */
5484 facility[2]= 0; /* returncode */
5485 }
5486 else facility[2]= 0xff;
5487 }
5488 else
5489 {
5490 /* reject */
5491 facility[2]= 0xff; /* returncode */
5492 }
5493 facility[0]= 2;
5494 facility[1]= MWI_RESPONSE; /* Function */
5495 add_p(plci,CAI,facility);
5496 add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5497 sig_req(plci,S_SERVICE,0);
5498 send_req(plci);
5499 plci->command = 0;
5500 next_internal_command (Id, plci);
5501 break;
5502 case CONF_ADD: /* OK */
5503 case CONF_BEGIN:
5504 case CONF_DROP:
5505 case CONF_ISOLATE:
5506 case CONF_REATTACH:
5507 case CONF_PARTYDISC:
5508 CONF_Ind[0]=9;
5509 CONF_Ind[3]=6;
5510 switch(pty_cai[5])
5511 {
5512 case CONF_BEGIN:
5513 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5514 if(pty_cai[0]==6)
5515 {
5516 d=pty_cai[6];
5517 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5518 }
5519 else
5520 {
5521 PUT_DWORD(&CONF_Ind[6],0x0);
5522 }
5523 break;
5524 case CONF_ISOLATE:
5525 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5526 CONF_Ind[0]=5;
5527 CONF_Ind[3]=2;
5528 break;
5529 case CONF_REATTACH:
5530 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5531 CONF_Ind[0]=5;
5532 CONF_Ind[3]=2;
5533 break;
5534 case CONF_DROP:
5535 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5536 CONF_Ind[0]=5;
5537 CONF_Ind[3]=2;
5538 break;
5539 case CONF_ADD:
5540 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5541 d=pty_cai[6];
5542 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5543 tplci=plci->relatedPTYPLCI;
5544 if(tplci) tplci->ptyState = CONNECTED;
5545 break;
5546 case CONF_PARTYDISC:
5547 CONF_Ind[0]=7;
5548 CONF_Ind[3]=4;
5549 PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5550 d=pty_cai[6];
5551 PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5552 break;
5553 }
5554 plci->ptyState = CONNECTED;
5555 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5556 break;
5557 case CCBS_INFO_RETAIN:
5558 case CCBS_ERASECALLLINKAGEID:
5559 case CCBS_STOP_ALERTING:
5560 CONF_Ind[0]=5;
5561 CONF_Ind[3]=2;
5562 switch(pty_cai[5])
5563 {
5564 case CCBS_INFO_RETAIN:
5565 PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5566 break;
5567 case CCBS_STOP_ALERTING:
5568 PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5569 break;
5570 case CCBS_ERASECALLLINKAGEID:
5571 PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5572 CONF_Ind[0]=7;
5573 CONF_Ind[3]=4;
5574 CONF_Ind[6]=0;
5575 CONF_Ind[7]=0;
5576 break;
5577 }
5578 w=pty_cai[6];
5579 PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5580
5581 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5582 {
5583 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5584 }
5585 else
5586 {
5587 for(i=0; i<max_appl; i++)
5588 if(a->Notification_Mask[i]&SMASK_CCBS)
5589 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5590 }
5591 break;
5592 }
5593 break;
5594 case CALL_HOLD_REJ:
5595 cau = parms[7];
5596 if(cau)
5597 {
5598 i = _L3_CAUSE | cau[2];
5599 if(cau[2]==0) i = 0x3603;
5600 }
5601 else
5602 {
5603 i = 0x3603;
5604 }
5605 PUT_WORD(&SS_Ind[1],S_HOLD);
5606 PUT_WORD(&SS_Ind[4],i);
5607 if(plci->SuppState == HOLD_REQUEST)
5608 {
5609 plci->SuppState = IDLE;
5610 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5611 }
5612 break;
5613
5614 case CALL_HOLD_ACK:
5615 if(plci->SuppState == HOLD_REQUEST)
5616 {
5617 plci->SuppState = CALL_HELD;
5618 CodecIdCheck(a, plci);
5619 start_internal_command (Id, plci, hold_save_command);
5620 }
5621 break;
5622
5623 case CALL_RETRIEVE_REJ:
5624 cau = parms[7];
5625 if(cau)
5626 {
5627 i = _L3_CAUSE | cau[2];
5628 if(cau[2]==0) i = 0x3603;
5629 }
5630 else
5631 {
5632 i = 0x3603;
5633 }
5634 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5635 PUT_WORD(&SS_Ind[4],i);
5636 if(plci->SuppState == RETRIEVE_REQUEST)
5637 {
5638 plci->SuppState = CALL_HELD;
5639 CodecIdCheck(a, plci);
5640 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5641 }
5642 break;
5643
5644 case CALL_RETRIEVE_ACK:
5645 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5646 if(plci->SuppState == RETRIEVE_REQUEST)
5647 {
5648 plci->SuppState = IDLE;
5649 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5650 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5651 if(plci->tel)
5652 {
5653 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5654 dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5655 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5656 if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5657 {
5658 dbug(1,dprintf("Get B-ch"));
5659 start_internal_command (Id, plci, retrieve_restore_command);
5660 }
5661 else
5662 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5663 }
5664 else
5665 start_internal_command (Id, plci, retrieve_restore_command);
5666 }
5667 break;
5668
5669 case INDICATE_IND:
5670 if(plci->State != LISTENING) {
5671 sig_req(plci,HANGUP,0);
5672 send_req(plci);
5673 break;
5674 }
5675 cip = find_cip(a,parms[4],parms[6]);
5676 cip_mask = 1L<<cip;
5677 dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5678 clear_c_ind_mask (plci);
5679 if (!remove_started && !a->adapter_disabled)
5680 {
5681 set_c_ind_mask_bit (plci, MAX_APPL);
5682 group_optimization(a, plci);
5683 for(i=0; i<max_appl; i++) {
5684 if(application[i].Id
5685 && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5686 && CPN_filter_ok(parms[0],a,i)
5687 && test_group_ind_mask_bit (plci, i) ) {
5688 dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5689 set_c_ind_mask_bit (plci, i);
5690 dump_c_ind_mask (plci);
5691 plci->State = INC_CON_PENDING;
5692 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5693 CALL_DIR_IN | CALL_DIR_ANSWER;
5694 if(esc_chi[0]) {
5695 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5696 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5697 }
5698 /* if a listen on the ext controller is done, check if hook states */
5699 /* are supported or if just a on board codec must be activated */
5700 if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5701 if(a->profile.Global_Options & HANDSET)
5702 plci->tel = ADV_VOICE;
5703 else if(a->profile.Global_Options & ON_BOARD_CODEC)
5704 plci->tel = CODEC;
5705 if(plci->tel) Id|=EXT_CONTROLLER;
5706 a->codec_listen[i] = plci;
5707 }
5708
5709 sendf(&application[i],_CONNECT_I,Id,0,
5710 "wSSSSSSSbSSSSS", cip, /* CIP */
5711 parms[0], /* CalledPartyNumber */
5712 multi_CiPN_parms[0], /* CallingPartyNumber */
5713 parms[2], /* CalledPartySubad */
5714 parms[3], /* CallingPartySubad */
5715 parms[4], /* BearerCapability */
5716 parms[5], /* LowLC */
5717 parms[6], /* HighLC */
5718 ai_len, /* nested struct add_i */
5719 add_i[0], /* B channel info */
5720 add_i[1], /* keypad facility */
5721 add_i[2], /* user user data */
5722 add_i[3], /* nested facility */
5723 multi_CiPN_parms[1] /* second CiPN(SCR) */
5724 );
5725 SendSSExtInd(&application[i],
5726 plci,
5727 Id,
5728 multi_ssext_parms);
5729 SendSetupInfo(&application[i],
5730 plci,
5731 Id,
5732 parms,
5733 SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, TRUE));
5734 }
5735 }
5736 clear_c_ind_mask_bit (plci, MAX_APPL);
5737 dump_c_ind_mask (plci);
5738 }
5739 if(c_ind_mask_empty (plci)) {
5740 sig_req(plci,HANGUP,0);
5741 send_req(plci);
5742 plci->State = IDLE;
5743 }
5744 plci->notifiedcall = 0;
5745 a->listen_active--;
5746 listen_check(a);
5747 break;
5748
5749 case CALL_PEND_NOTIFY:
5750 plci->notifiedcall = 1;
5751 listen_check(a);
5752 break;
5753
5754 case CALL_IND:
5755 case CALL_CON:
5756 if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5757 {
5758 if(plci->internal_command==PERM_COD_CONN_PEND)
5759 {
5760 if(plci->State==ADVANCED_VOICE_NOSIG)
5761 {
5762 dbug(1,dprintf("***Codec OK"));
5763 if(a->AdvSignalPLCI)
5764 {
5765 tplci = a->AdvSignalPLCI;
5766 if(tplci->spoofed_msg)
5767 {
5768 dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5769 tplci->command = 0;
5770 tplci->internal_command = 0;
5771 x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5772 switch (tplci->spoofed_msg)
5773 {
5774 case CALL_RES:
5775 tplci->command = _CONNECT_I|RESPONSE;
5776 api_load_msg (&tplci->saved_msg, saved_parms);
5777 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5778 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5779 {
5780 /* early B3 connect (CIP mask bit 9) no release after a disc */
5781 add_p(tplci,LLI,"\x01\x01");
5782 }
5783 add_s(tplci, CONN_NR, &saved_parms[2]);
5784 add_s(tplci, LLC, &saved_parms[4]);
5785 add_ai(tplci, &saved_parms[5]);
5786 tplci->State = INC_CON_ACCEPT;
5787 sig_req(tplci, CALL_RES,0);
5788 send_req(tplci);
5789 break;
5790
5791 case AWAITING_SELECT_B:
5792 dbug(1,dprintf("Select_B continue"));
5793 start_internal_command (x_Id, tplci, select_b_command);
5794 break;
5795
5796 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5797 if(!tplci->Sig.Id)
5798 {
5799 dbug(1,dprintf("No SigID!"));
5800 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5801 plci_remove(tplci);
5802 break;
5803 }
5804 tplci->command = _MANUFACTURER_R;
5805 api_load_msg (&tplci->saved_msg, saved_parms);
5806 dir = saved_parms[2].info[0];
5807 if(dir==1) {
5808 sig_req(tplci,CALL_REQ,0);
5809 }
5810 else if(!dir){
5811 sig_req(tplci,LISTEN_REQ,0);
5812 }
5813 send_req(tplci);
5814 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5815 break;
5816
5817 case (CALL_REQ|AWAITING_MANUF_CON):
5818 sig_req(tplci,CALL_REQ,0);
5819 send_req(tplci);
5820 break;
5821
5822 case CALL_REQ:
5823 if(!tplci->Sig.Id)
5824 {
5825 dbug(1,dprintf("No SigID!"));
5826 sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5827 plci_remove(tplci);
5828 break;
5829 }
5830 tplci->command = _CONNECT_R;
5831 api_load_msg (&tplci->saved_msg, saved_parms);
5832 add_s(tplci,CPN,&saved_parms[1]);
5833 add_s(tplci,DSA,&saved_parms[3]);
5834 add_ai(tplci,&saved_parms[9]);
5835 sig_req(tplci,CALL_REQ,0);
5836 send_req(tplci);
5837 break;
5838
5839 case CALL_RETRIEVE:
5840 tplci->command = C_RETRIEVE_REQ;
5841 sig_req(tplci,CALL_RETRIEVE,0);
5842 send_req(tplci);
5843 break;
5844 }
5845 tplci->spoofed_msg = 0;
5846 if (tplci->internal_command == 0)
5847 next_internal_command (x_Id, tplci);
5848 }
5849 }
5850 next_internal_command (Id, plci);
5851 break;
5852 }
5853 dbug(1,dprintf("***Codec Hook Init Req"));
5854 plci->internal_command = PERM_COD_HOOK;
5855 add_p(plci,FTY,"\x01\x09"); /* Get Hook State*/
5856 sig_req(plci,TEL_CTRL,0);
5857 send_req(plci);
5858 }
5859 }
5860 else if(plci->command != _MANUFACTURER_R /* old style permanent connect */
5861 && plci->State!=INC_ACT_PENDING)
5862 {
5863 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5864 if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5865 {
5866 chi[2] = plci->b_channel;
5867 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5868 }
5869 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5870 plci->State = INC_ACT_PENDING;
5871 }
5872 break;
5873
5874 case TEL_CTRL:
5875 Number = 0;
5876 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5877 if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5878 switch (ie[1]&0x91) {
5879 case 0x80: /* hook off */
5880 case 0x81:
5881 if(plci->internal_command==PERM_COD_HOOK)
5882 {
5883 dbug(1,dprintf("init:hook_off"));
5884 plci->hook_state = ie[1];
5885 next_internal_command (Id, plci);
5886 break;
5887 }
5888 else /* ignore doubled hook indications */
5889 {
5890 if( ((plci->hook_state)&0xf0)==0x80)
5891 {
5892 dbug(1,dprintf("ignore hook"));
5893 break;
5894 }
5895 plci->hook_state = ie[1]&0x91;
5896 }
5897 /* check for incoming call pending */
5898 /* and signal '+'.Appl must decide */
5899 /* with connect_res if call must */
5900 /* accepted or not */
5901 for(i=0, tplci=NULL;i<max_appl;i++){
5902 if(a->codec_listen[i]
5903 && (a->codec_listen[i]->State==INC_CON_PENDING
5904 ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5905 tplci = a->codec_listen[i];
5906 tplci->appl = &application[i];
5907 }
5908 }
5909 /* no incoming call, do outgoing call */
5910 /* and signal '+' if outg. setup */
5911 if(!a->AdvSignalPLCI && !tplci){
5912 if((i=get_plci(a))) {
5913 a->AdvSignalPLCI = &a->plci[i-1];
5914 tplci = a->AdvSignalPLCI;
5915 tplci->tel = ADV_VOICE;
5916 PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5917 if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5918 /* early B3 connect (CIP mask bit 9) no release after a disc */
5919 add_p(tplci,LLI,"\x01\x01");
5920 }
5921 add_p(tplci, CAI, voice_cai);
5922 add_p(tplci, OAD, a->TelOAD);
5923 add_p(tplci, OSA, a->TelOSA);
5924 add_p(tplci,SHIFT|6,NULL);
5925 add_p(tplci,SIN,"\x02\x01\x00");
5926 add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5927 sig_req(tplci,ASSIGN,DSIG_ID);
5928 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5929 a->AdvSignalPLCI->command = 0;
5930 tplci->appl = a->AdvSignalAppl;
5931 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5932 send_req(tplci);
5933 }
5934
5935 }
5936
5937 if(!tplci) break;
5938 Id = ((word)tplci->Id<<8)|a->Id;
5939 Id|=EXT_CONTROLLER;
5940 sendf(tplci->appl,
5941 _FACILITY_I,
5942 Id,
5943 0,
5944 "ws", (word)0, "\x01+");
5945 break;
5946
5947 case 0x90: /* hook on */
5948 case 0x91:
5949 if(plci->internal_command==PERM_COD_HOOK)
5950 {
5951 dbug(1,dprintf("init:hook_on"));
5952 plci->hook_state = ie[1]&0x91;
5953 next_internal_command (Id, plci);
5954 break;
5955 }
5956 else /* ignore doubled hook indications */
5957 {
5958 if( ((plci->hook_state)&0xf0)==0x90) break;
5959 plci->hook_state = ie[1]&0x91;
5960 }
5961 /* hangup the adv. voice call and signal '-' to the appl */
5962 if(a->AdvSignalPLCI) {
5963 Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5964 if(plci->tel) Id|=EXT_CONTROLLER;
5965 sendf(a->AdvSignalAppl,
5966 _FACILITY_I,
5967 Id,
5968 0,
5969 "ws", (word)0, "\x01-");
5970 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5971 a->AdvSignalPLCI->command = 0;
5972 sig_req(a->AdvSignalPLCI,HANGUP,0);
5973 send_req(a->AdvSignalPLCI);
5974 }
5975 break;
5976 }
5977 }
5978 break;
5979
5980 case RESUME:
5981 clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
5982 PUT_WORD(&resume_cau[4],GOOD);
5983 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
5984 break;
5985
5986 case SUSPEND:
5987 clear_c_ind_mask (plci);
5988
5989 if (plci->NL.Id && !plci->nl_remove_id) {
5990 mixer_remove (plci);
5991 nl_req_ncci(plci,REMOVE,0);
5992 }
5993 if (!plci->sig_remove_id) {
5994 plci->internal_command = 0;
5995 sig_req(plci,REMOVE,0);
5996 }
5997 send_req(plci);
5998 if(!plci->channels) {
5999 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6000 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6001 }
6002 break;
6003
6004 case SUSPEND_REJ:
6005 break;
6006
6007 case HANGUP:
6008 plci->hangup_flow_ctrl_timer=0;
6009 if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6010 cau = parms[7];
6011 if(cau) {
6012 i = _L3_CAUSE | cau[2];
6013 if(cau[2]==0) i = 0;
6014 else if(cau[2]==8) i = _L1_ERROR;
6015 else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6016 else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6017 }
6018 else {
6019 i = _L3_ERROR;
6020 }
6021
6022 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6023 {
6024 for(i=0; i<max_appl; i++)
6025 {
6026 if(test_c_ind_mask_bit (plci, i))
6027 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6028 }
6029 }
6030 else
6031 {
6032 clear_c_ind_mask (plci);
6033 }
6034 if(!plci->appl)
6035 {
6036 if (plci->State == LISTENING)
6037 {
6038 plci->notifiedcall=0;
6039 a->listen_active--;
6040 }
6041 plci->State = INC_DIS_PENDING;
6042 if(c_ind_mask_empty (plci))
6043 {
6044 plci->State = IDLE;
6045 if (plci->NL.Id && !plci->nl_remove_id)
6046 {
6047 mixer_remove (plci);
6048 nl_req_ncci(plci,REMOVE,0);
6049 }
6050 if (!plci->sig_remove_id)
6051 {
6052 plci->internal_command = 0;
6053 sig_req(plci,REMOVE,0);
6054 }
6055 send_req(plci);
6056 }
6057 }
6058 else
6059 {
6060 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6061 /* result in a second HANGUP! Don't generate another */
6062 /* DISCONNECT */
6063 if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6064 {
6065 if(plci->State==RESUMING)
6066 {
6067 PUT_WORD(&resume_cau[4],i);
6068 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6069 }
6070 plci->State = INC_DIS_PENDING;
6071 sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6072 }
6073 }
6074 break;
6075
6076 case SSEXT_IND:
6077 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6078 break;
6079
6080 case VSWITCH_REQ:
6081 VSwitchReqInd(plci,Id,multi_vswitch_parms);
6082 break;
6083 case VSWITCH_IND:
6084 if(plci->relatedPTYPLCI &&
6085 plci->vswitchstate==3 &&
6086 plci->relatedPTYPLCI->vswitchstate==3 &&
6087 parms[MAXPARMSIDS-1][0])
6088 {
6089 add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6090 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6091 send_req(plci->relatedPTYPLCI);
6092 }
6093 else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6094 break;
6095
6096 }
6097}
6098
6099
6100static void SendSetupInfo(APPL * appl, PLCI * plci, dword Id, byte * * parms, byte Info_Sent_Flag)
6101{
6102 word i;
6103 byte * ie;
6104 word Info_Number;
6105 byte * Info_Element;
6106 word Info_Mask = 0;
6107
6108 dbug(1,dprintf("SetupInfo"));
6109
6110 for(i=0; i<MAXPARMSIDS; i++) {
6111 ie = parms[i];
6112 Info_Number = 0;
6113 Info_Element = ie;
6114 if(ie[0]) {
6115 switch(i) {
6116 case 0:
6117 dbug(1,dprintf("CPN "));
6118 Info_Number = 0x0070;
6119 Info_Mask = 0x80;
6120 Info_Sent_Flag = TRUE;
6121 break;
6122 case 8: /* display */
6123 dbug(1,dprintf("display(%d)",i));
6124 Info_Number = 0x0028;
6125 Info_Mask = 0x04;
6126 Info_Sent_Flag = TRUE;
6127 break;
6128 case 16: /* Channel Id */
6129 dbug(1,dprintf("CHI"));
6130 Info_Number = 0x0018;
6131 Info_Mask = 0x100;
6132 Info_Sent_Flag = TRUE;
6133 mixer_set_bchannel_id (plci, Info_Element);
6134 break;
6135 case 19: /* Redirected Number */
6136 dbug(1,dprintf("RDN"));
6137 Info_Number = 0x0074;
6138 Info_Mask = 0x400;
6139 Info_Sent_Flag = TRUE;
6140 break;
6141 case 20: /* Redirected Number extended */
6142 dbug(1,dprintf("RDX"));
6143 Info_Number = 0x0073;
6144 Info_Mask = 0x400;
6145 Info_Sent_Flag = TRUE;
6146 break;
6147 case 22: /* Redirecing Number */
6148 dbug(1,dprintf("RIN"));
6149 Info_Number = 0x0076;
6150 Info_Mask = 0x400;
6151 Info_Sent_Flag = TRUE;
6152 break;
6153 default:
6154 Info_Number = 0;
6155 break;
6156 }
6157 }
6158
6159 if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6160 Info_Number = 0x8000 |5;
6161 Info_Mask = 0x10;
6162 Info_Element = "";
6163 }
6164
6165 if(Info_Sent_Flag && Info_Number){
6166 if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6167 sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6168 }
6169 }
6170 }
6171}
6172
6173
6174void SendInfo(PLCI * plci, dword Id, byte * * parms, byte iesent)
6175{
6176 word i;
6177 word j;
6178 word k;
6179 byte * ie;
6180 word Info_Number;
6181 byte * Info_Element;
6182 word Info_Mask = 0;
6183 static byte charges[5] = {4,0,0,0,0};
6184 static byte cause[] = {0x02,0x80,0x00};
6185 APPL *appl;
6186
6187 dbug(1,dprintf("InfoParse "));
6188
6189 if(
6190 !plci->appl
6191 && !plci->State
6192 && plci->Sig.Ind!=NCR_FACILITY
6193 )
6194 {
6195 dbug(1,dprintf("NoParse "));
6196 return;
6197 }
6198 cause[2] = 0;
6199 for(i=0; i<MAXPARMSIDS; i++) {
6200 ie = parms[i];
6201 Info_Number = 0;
6202 Info_Element = ie;
6203 if(ie[0]) {
6204 switch(i) {
6205 case 0:
6206 dbug(1,dprintf("CPN "));
6207 Info_Number = 0x0070;
6208 Info_Mask = 0x80;
6209 break;
6210 case 7: /* ESC_CAU */
6211 dbug(1,dprintf("cau(0x%x)",ie[2]));
6212 Info_Number = 0x0008;
6213 Info_Mask = 0x00;
6214 cause[2] = ie[2];
6215 Info_Element = NULL;
6216 break;
6217 case 8: /* display */
6218 dbug(1,dprintf("display(%d)",i));
6219 Info_Number = 0x0028;
6220 Info_Mask = 0x04;
6221 break;
6222 case 9: /* Date display */
6223 dbug(1,dprintf("date(%d)",i));
6224 Info_Number = 0x0029;
6225 Info_Mask = 0x02;
6226 break;
6227 case 10: /* charges */
6228 for(j=0;j<4;j++) charges[1+j] = 0;
6229 for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6230 for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6231 Info_Number = 0x4000;
6232 Info_Mask = 0x40;
6233 Info_Element = charges;
6234 break;
6235 case 11: /* user user info */
6236 dbug(1,dprintf("uui"));
6237 Info_Number = 0x007E;
6238 Info_Mask = 0x08;
6239 break;
6240 case 12: /* congestion receiver ready */
6241 dbug(1,dprintf("clRDY"));
6242 Info_Number = 0x00B0;
6243 Info_Mask = 0x08;
6244 Info_Element = "";
6245 break;
6246 case 13: /* congestion receiver not ready */
6247 dbug(1,dprintf("clNRDY"));
6248 Info_Number = 0x00BF;
6249 Info_Mask = 0x08;
6250 Info_Element = "";
6251 break;
6252 case 15: /* Keypad Facility */
6253 dbug(1,dprintf("KEY"));
6254 Info_Number = 0x002C;
6255 Info_Mask = 0x20;
6256 break;
6257 case 16: /* Channel Id */
6258 dbug(1,dprintf("CHI"));
6259 Info_Number = 0x0018;
6260 Info_Mask = 0x100;
6261 mixer_set_bchannel_id (plci, Info_Element);
6262 break;
6263 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6264 dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6265 if(!cause[2] || cause[2]<0x80) break; /* eg. layer 1 error */
6266 Info_Number = 0x0008;
6267 Info_Mask = 0x01;
6268 if(cause[2] != ie[2]) Info_Element = cause;
6269 break;
6270 case 19: /* Redirected Number */
6271 dbug(1,dprintf("RDN"));
6272 Info_Number = 0x0074;
6273 Info_Mask = 0x400;
6274 break;
6275 case 22: /* Redirecing Number */
6276 dbug(1,dprintf("RIN"));
6277 Info_Number = 0x0076;
6278 Info_Mask = 0x400;
6279 break;
6280 case 23: /* Notification Indicator */
6281 dbug(1,dprintf("NI"));
6282 Info_Number = (word)NI;
6283 Info_Mask = 0x210;
6284 break;
6285 case 26: /* Call State */
6286 dbug(1,dprintf("CST"));
6287 Info_Number = (word)CST;
6288 Info_Mask = 0x01; /* do with cause i.e. for now */
6289 break;
6290 case MAXPARMSIDS-2: /* Escape Message Type, must be the last indication */
6291 dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6292 Info_Number = 0x8000 |ie[3];
6293 if(iesent) Info_Mask = 0xffff;
6294 else Info_Mask = 0x10;
6295 Info_Element = "";
6296 break;
6297 default:
6298 Info_Number = 0;
6299 Info_Mask = 0;
6300 Info_Element = "";
6301 break;
6302 }
6303 }
6304
6305 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6306 {
6307 for(j=0; j<max_appl; j++)
6308 {
6309 appl = &application[j];
6310 if(Info_Number
6311 && appl->Id
6312 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6313 {
6314 dbug(1,dprintf("NCR_Ind"));
6315 iesent=TRUE;
6316 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6317 }
6318 }
6319 }
6320 else if(!plci->appl)
6321 { /* overlap receiving broadcast */
6322 if(Info_Number==CPN
6323 || Info_Number==KEY
6324 || Info_Number==NI
6325 || Info_Number==DSP
6326 || Info_Number==UUI )
6327 {
6328 for(j=0; j<max_appl; j++)
6329 {
6330 if(test_c_ind_mask_bit (plci, j))
6331 {
6332 dbug(1,dprintf("Ovl_Ind"));
6333 iesent=TRUE;
6334 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6335 }
6336 }
6337 }
6338 } /* all other signalling states */
6339 else if(Info_Number
6340 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6341 {
6342 dbug(1,dprintf("Std_Ind"));
6343 iesent=TRUE;
6344 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6345 }
6346 }
6347}
6348
6349
6350byte SendMultiIE(PLCI * plci, dword Id, byte * * parms, byte ie_type, dword info_mask, byte setupParse)
6351{
6352 word i;
6353 word j;
6354 byte * ie;
6355 word Info_Number;
6356 byte * Info_Element;
6357 APPL *appl;
6358 word Info_Mask = 0;
6359 byte iesent=0;
6360
6361 if(
6362 !plci->appl
6363 && !plci->State
6364 && plci->Sig.Ind!=NCR_FACILITY
6365 && !setupParse
6366 )
6367 {
6368 dbug(1,dprintf("NoM-IEParse "));
6369 return 0;
6370 }
6371 dbug(1,dprintf("M-IEParse "));
6372
6373 for(i=0; i<MAX_MULTI_IE; i++)
6374 {
6375 ie = parms[i];
6376 Info_Number = 0;
6377 Info_Element = ie;
6378 if(ie[0])
6379 {
6380 dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6381 Info_Number = (word)ie_type;
6382 Info_Mask = (word)info_mask;
6383 }
6384
6385 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6386 {
6387 for(j=0; j<max_appl; j++)
6388 {
6389 appl = &application[j];
6390 if(Info_Number
6391 && appl->Id
6392 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6393 {
6394 iesent = TRUE;
6395 dbug(1,dprintf("Mlt_NCR_Ind"));
6396 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6397 }
6398 }
6399 }
6400 else if(!plci->appl && Info_Number)
6401 { /* overlap receiving broadcast */
6402 for(j=0; j<max_appl; j++)
6403 {
6404 if(test_c_ind_mask_bit (plci, j))
6405 {
6406 iesent = TRUE;
6407 dbug(1,dprintf("Mlt_Ovl_Ind"));
6408 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6409 }
6410 }
6411 } /* all other signalling states */
6412 else if(Info_Number
6413 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6414 {
6415 iesent = TRUE;
6416 dbug(1,dprintf("Mlt_Std_Ind"));
6417 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6418 }
6419 }
6420 return iesent;
6421}
6422
6423static void SendSSExtInd(APPL * appl, PLCI * plci, dword Id, byte * * parms)
6424{
6425 word i;
6426 /* Format of multi_ssext_parms[i][]:
6427 0 byte length
6428 1 byte SSEXTIE
6429 2 byte SSEXT_REQ/SSEXT_IND
6430 3 byte length
6431 4 word SSExtCommand
6432 6... Params
6433 */
6434 if(
6435 plci
6436 && plci->State
6437 && plci->Sig.Ind!=NCR_FACILITY
6438 )
6439 for(i=0;i<MAX_MULTI_IE;i++)
6440 {
6441 if(parms[i][0]<6) continue;
6442 if(parms[i][2]==SSEXT_REQ) continue;
6443
6444 if(appl)
6445 {
6446 parms[i][0]=0; /* kill it */
6447 sendf(appl,_MANUFACTURER_I,
6448 Id,
6449 0,
6450 "dwS",
6451 _DI_MANU_ID,
6452 _DI_SSEXT_CTRL,
6453 &parms[i][3]);
6454 }
6455 else if(plci->appl)
6456 {
6457 parms[i][0]=0; /* kill it */
6458 sendf(plci->appl,_MANUFACTURER_I,
6459 Id,
6460 0,
6461 "dwS",
6462 _DI_MANU_ID,
6463 _DI_SSEXT_CTRL,
6464 &parms[i][3]);
6465 }
6466 }
6467};
6468
6469void nl_ind(PLCI * plci)
6470{
6471 byte ch;
6472 word ncci;
6473 dword Id;
6474 DIVA_CAPI_ADAPTER * a;
6475 word NCCIcode;
6476 APPL * APPLptr;
6477 word count;
6478 word Num;
6479 word i, ncpi_state;
6480 byte len, ncci_state;
6481 word msg;
6482 word info = 0;
6483 word fax_feature_bits;
6484 byte fax_send_edata_ack;
6485 static byte v120_header_buffer[2 + 3];
6486 static word fax_info[] = {
6487 0, /* T30_SUCCESS */
6488 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6489 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6490 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6491 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6492 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6493 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6494 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6495 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6496 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6497 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6498 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6499 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6500 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6501 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6502 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6503 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6504 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6505 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6506 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6507 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6508 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6509 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6510 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6511 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6512 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6513 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6514 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6515 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6516 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6517 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6518 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6519 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6520 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6521 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6522 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6523 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6524 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6525 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6526 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6527 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6528 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6529 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6530 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6531 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6532 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6533 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6534 };
6535
6536 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6537
6538
6539 static word rtp_info[] = {
6540 GOOD, /* RTP_SUCCESS */
6541 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6542 };
6543
6544 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6545 {
6546 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6547 0x00000000, 0x00000000, 0x00000000, 0x00000000
6548 };
6549
6550 ch = plci->NL.IndCh;
6551 a = plci->adapter;
6552 ncci = a->ch_ncci[ch];
6553 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6554 if(plci->tel) Id|=EXT_CONTROLLER;
6555 APPLptr = plci->appl;
6556 dbug(1,dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x",
6557 plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6558
6559 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6560
6561 if (plci->nl_remove_id)
6562 {
6563 plci->NL.RNR = 2; /* discard */
6564 dbug(1,dprintf("NL discard while remove pending"));
6565 return;
6566 }
6567 if((plci->NL.Ind &0x0f)==N_CONNECT)
6568 {
6569 if(plci->State==INC_DIS_PENDING
6570 || plci->State==OUTG_DIS_PENDING
6571 || plci->State==IDLE)
6572 {
6573 plci->NL.RNR = 2; /* discard */
6574 dbug(1,dprintf("discard n_connect"));
6575 return;
6576 }
6577 if(plci->State < INC_ACT_PENDING)
6578 {
6579 plci->NL.RNR = 1; /* flow control */
6580 channel_x_off (plci, ch, N_XON_CONNECT_IND);
6581 return;
6582 }
6583 }
6584
6585 if(!APPLptr) /* no application or invalid data */
6586 { /* while reloading the DSP */
6587 dbug(1,dprintf("discard1"));
6588 plci->NL.RNR = 2;
6589 return;
6590 }
6591
6592 if (((plci->NL.Ind &0x0f) == N_UDATA)
6593 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6594 || (plci->B2_prot == 7)
6595 || (plci->B3_prot == 7)) )
6596 {
6597 plci->ncpi_buffer[0] = 0;
6598
6599 ncpi_state = plci->ncpi_state;
6600 if (plci->NL.complete == 1)
6601 {
6602 byte * data = &plci->NL.RBuffer->P[0];
6603
6604 if ((plci->NL.RBuffer->length >= 12)
6605 &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6606 ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6607 {
6608 word conn_opt, ncpi_opt = 0x00;
6609/* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6610
6611 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6612 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6613 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6614 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6615
6616 data++; /* indication code */
6617 data += 2; /* timestamp */
6618 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6619 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6620 data++; /* connected norm */
6621 conn_opt = GET_WORD(data);
6622 data += 2; /* connected options */
6623
6624 PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6625
6626 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6627 {
6628 ncpi_opt |= MDM_NCPI_ECM_V42;
6629 }
6630 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6631 {
6632 ncpi_opt |= MDM_NCPI_ECM_MNP;
6633 }
6634 else
6635 {
6636 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6637 }
6638 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6639 {
6640 ncpi_opt |= MDM_NCPI_COMPRESSED;
6641 }
6642 PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6643 plci->ncpi_buffer[0] = 4;
6644
6645 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6646 }
6647 }
6648 if (plci->B3_prot == 7)
6649 {
6650 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6651 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6652 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6653 {
6654 a->ncci_state[ncci] = INC_ACT_PENDING;
6655 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6656 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6657 }
6658 }
6659
6660 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6661 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6662 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6663 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6664
6665 {
6666 plci->NL.RNR = 2;
6667 return;
6668 }
6669 }
6670
6671 if(plci->NL.complete == 2)
6672 {
6673 if (((plci->NL.Ind &0x0f) == N_UDATA)
6674 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6675 {
6676 switch(plci->RData[0].P[0])
6677 {
6678
6679 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6680 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6681 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6682 break;
6683 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6684 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6685 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6686 break;
6687 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6688 dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6689 break;
6690 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6691 dtmf_confirmation (Id, plci);
6692 break;
6693
6694
6695 case UDATA_INDICATION_MIXER_TAP_DATA:
6696 capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6697 i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6698 if (i != 0)
6699 {
6700 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6701 dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6702 }
6703 break;
6704
6705
6706 case UDATA_INDICATION_MIXER_COEFS_SET:
6707 mixer_indication_coefs_set (Id, plci);
6708 break;
6709 case UDATA_INDICATION_XCONNECT_FROM:
6710 mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6711 break;
6712 case UDATA_INDICATION_XCONNECT_TO:
6713 mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6714 break;
6715
6716
6717 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6718 ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6719 break;
6720
6721
6722
6723 default:
6724 break;
6725 }
6726 }
6727 else
6728 {
6729 if ((plci->RData[0].PLength != 0)
6730 && ((plci->B2_prot == B2_V120_ASYNC)
6731 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6732 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6733 {
6734
6735 sendf(plci->appl,_DATA_B3_I,Id,0,
6736 "dwww",
6737 plci->RData[1].P,
6738 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6739 plci->RNum,
6740 plci->RFlags);
6741
6742 }
6743 else
6744 {
6745
6746 sendf(plci->appl,_DATA_B3_I,Id,0,
6747 "dwww",
6748 plci->RData[0].P,
6749 plci->RData[0].PLength,
6750 plci->RNum,
6751 plci->RFlags);
6752
6753 }
6754 }
6755 return;
6756 }
6757
6758 fax_feature_bits = 0;
6759 if((plci->NL.Ind &0x0f)==N_CONNECT ||
6760 (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6761 (plci->NL.Ind &0x0f)==N_DISC ||
6762 (plci->NL.Ind &0x0f)==N_EDATA ||
6763 (plci->NL.Ind &0x0f)==N_DISC_ACK)
6764 {
6765 info = 0;
6766 plci->ncpi_buffer[0] = 0;
6767 switch (plci->B3_prot) {
6768 case 0: /*XPARENT*/
6769 case 1: /*T.90 NL*/
6770 break; /* no network control protocol info - jfr */
6771 case 2: /*ISO8202*/
6772 case 3: /*X25 DCE*/
6773 for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6774 plci->ncpi_buffer[0] = (byte)(i+3);
6775 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6776 plci->ncpi_buffer[2] = 0;
6777 plci->ncpi_buffer[3] = 0;
6778 break;
6779 case 4: /*T.30 - FAX*/
6780 case 5: /*T.30 - FAX*/
6781 if(plci->NL.RLength>=sizeof(T30_INFO))
6782 {
6783 dbug(1,dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6784 len = 9;
6785 PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6786 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6787 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6788 if (plci->B3_prot == 5)
6789 {
6790 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6791 i |= 0x8000; /* This is not an ECM connection */
6792 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6793 i |= 0x4000; /* This is a connection with MMR compression */
6794 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6795 i |= 0x2000; /* This is a connection with MR compression */
6796 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6797 i |= 0x0004; /* More documents */
6798 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6799 i |= 0x0002; /* Fax-polling indication */
6800 }
6801 dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6802 PUT_WORD(&(plci->ncpi_buffer[3]),i);
6803 PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6804 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6805 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6806 plci->ncpi_buffer[len] = 0;
6807 if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6808 {
6809 plci->ncpi_buffer[len] = 20;
6810 for (i = 0; i < 20; i++)
6811 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6812 }
6813 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6814 {
6815 if (((T30_INFO *)plci->NL.RBuffer->P)->code < sizeof(fax_info) / sizeof(fax_info[0]))
6816 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6817 else
6818 info = _FAX_PROTOCOL_ERROR;
6819 }
6820
6821 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6822 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6823 {
6824 i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6825 while (i < plci->NL.RBuffer->length)
6826 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6827 }
6828
6829 plci->ncpi_buffer[0] = len;
6830 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6831 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6832
6833 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6834 if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6835 || (((plci->NL.Ind &0x0f) == N_CONNECT)
6836 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6837 || (((plci->NL.Ind &0x0f) == N_EDATA)
6838 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6839 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6840 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6841 {
6842 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6843 }
6844 if (((plci->NL.Ind &0x0f) == N_DISC)
6845 || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6846 || (((plci->NL.Ind &0x0f) == N_EDATA)
6847 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6848 {
6849 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6850 }
6851 }
6852 break;
6853
6854 case B3_RTP:
6855 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6856 {
6857 if (plci->NL.RLength != 0)
6858 {
6859 info = rtp_info[plci->NL.RBuffer->P[0]];
6860 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6861 for (i = 1; i < plci->NL.RLength; i++)
6862 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6863 }
6864 }
6865 break;
6866
6867 }
6868 plci->NL.RNR = 2;
6869 }
6870 switch(plci->NL.Ind &0x0f) {
6871 case N_EDATA:
6872 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6873 {
6874 dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6875 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6876 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6877
6878 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6879 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6880 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6881 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6882 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6883 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6884 {
6885 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6886 sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6887 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6888 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6889 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6890 fax_send_edata_ack = FALSE;
6891 }
6892
6893 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6894 {
6895 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6896 {
6897 case EDATA_T30_DIS:
6898 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6899 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6900 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6901 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6902 {
6903 a->ncci_state[ncci] = INC_ACT_PENDING;
6904 if (plci->B3_prot == 4)
6905 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6906 else
6907 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6908 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6909 }
6910 break;
6911
6912 case EDATA_T30_TRAIN_OK:
6913 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6914 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6915 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6916 {
6917 if (plci->B3_prot == 4)
6918 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6919 else
6920 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6921 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6922 }
6923 break;
6924
6925 case EDATA_T30_EOP_CAPI:
6926 if (a->ncci_state[ncci] == CONNECTED)
6927 {
6928 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6929 a->ncci_state[ncci] = INC_DIS_PENDING;
6930 plci->ncpi_state = 0;
6931 fax_send_edata_ack = FALSE;
6932 }
6933 break;
6934 }
6935 }
6936 else
6937 {
6938 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6939 {
6940 case EDATA_T30_TRAIN_OK:
6941 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6942 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6943 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6944 {
6945 if (plci->B3_prot == 4)
6946 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6947 else
6948 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6949 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6950 }
6951 break;
6952 }
6953 }
6954 if (fax_send_edata_ack)
6955 {
6956 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6957 plci->fax_edata_ack_length = 1;
6958 start_internal_command (Id, plci, fax_edata_ack_command);
6959 }
6960 }
6961 else
6962 {
6963 dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6964 }
6965 break;
6966 case N_CONNECT:
6967 if (!a->ch_ncci[ch])
6968 {
6969 ncci = get_ncci (plci, ch, 0);
6970 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6971 }
6972 dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6973 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6974
6975 msg = _CONNECT_B3_I;
6976 if (a->ncci_state[ncci] == IDLE)
6977 plci->channels++;
6978 else if (plci->B3_prot == 1)
6979 msg = _CONNECT_B3_T90_ACTIVE_I;
6980
6981 a->ncci_state[ncci] = INC_CON_PENDING;
6982 if(plci->B3_prot == 4)
6983 sendf(plci->appl,msg,Id,0,"s","");
6984 else
6985 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
6986 break;
6987 case N_CONNECT_ACK:
6988 dbug(1,dprintf("N_connect_Ack"));
6989 if (plci->internal_command_queue[0]
6990 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6991 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6992 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6993 {
6994 (*(plci->internal_command_queue[0]))(Id, plci, 0);
6995 if (!plci->internal_command)
6996 next_internal_command (Id, plci);
6997 break;
6998 }
6999 msg = _CONNECT_B3_ACTIVE_I;
7000 if (plci->B3_prot == 1)
7001 {
7002 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7003 msg = _CONNECT_B3_T90_ACTIVE_I;
7004 a->ncci_state[ncci] = INC_ACT_PENDING;
7005 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7006 }
7007 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7008 {
7009 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7010 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7011 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7012 {
7013 a->ncci_state[ncci] = INC_ACT_PENDING;
7014 if (plci->B3_prot == 4)
7015 sendf(plci->appl,msg,Id,0,"s","");
7016 else
7017 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7018 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7019 }
7020 }
7021 else
7022 {
7023 a->ncci_state[ncci] = INC_ACT_PENDING;
7024 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7025 }
7026 if (plci->adjust_b_restore)
7027 {
7028 plci->adjust_b_restore = FALSE;
7029 start_internal_command (Id, plci, adjust_b_restore);
7030 }
7031 break;
7032 case N_DISC:
7033 case N_DISC_ACK:
7034 if (plci->internal_command_queue[0]
7035 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7036 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7037 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7038 {
7039 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7040 if (!plci->internal_command)
7041 next_internal_command (Id, plci);
7042 }
7043 ncci_state = a->ncci_state[ncci];
7044 ncci_remove (plci, ncci, FALSE);
7045
7046 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7047 /* channel, so we cannot store the state in ncci_state! The */
7048 /* information which channel we received a N_DISC is thus */
7049 /* stored in the inc_dis_ncci_table buffer. */
7050 for(i=0; plci->inc_dis_ncci_table[i]; i++);
7051 plci->inc_dis_ncci_table[i] = (byte) ncci;
7052
7053 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7054 if (!plci->channels
7055 && (plci->B1_resource == 16)
7056 && (plci->State <= CONNECTED))
7057 {
7058 len = 9;
7059 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7060 PUT_WORD (&plci->ncpi_buffer[1], i);
7061 PUT_WORD (&plci->ncpi_buffer[3], 0);
7062 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7063 PUT_WORD (&plci->ncpi_buffer[5], i);
7064 PUT_WORD (&plci->ncpi_buffer[7], 0);
7065 plci->ncpi_buffer[len] = 0;
7066 plci->ncpi_buffer[0] = len;
7067 if(plci->B3_prot == 4)
7068 sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7069 else
7070 {
7071
7072 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7073 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7074 {
7075 plci->ncpi_buffer[++len] = 0;
7076 plci->ncpi_buffer[++len] = 0;
7077 plci->ncpi_buffer[++len] = 0;
7078 plci->ncpi_buffer[0] = len;
7079 }
7080
7081 sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7082 }
7083 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7084 plci->ncpi_state = 0;
7085 sig_req(plci,HANGUP,0);
7086 send_req(plci);
7087 plci->State = OUTG_DIS_PENDING;
7088 /* disc here */
7089 }
7090 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7091 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7092 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7093 {
7094 if (ncci_state == IDLE)
7095 {
7096 if (plci->channels)
7097 plci->channels--;
7098 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7099 if(plci->State == SUSPENDING){
7100 sendf(plci->appl,
7101 _FACILITY_I,
7102 Id & 0xffffL,
7103 0,
7104 "ws", (word)3, "\x03\x04\x00\x00");
7105 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7106 }
7107 plci_remove(plci);
7108 plci->State=IDLE;
7109 }
7110 }
7111 }
7112 else if (plci->channels)
7113 {
7114 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7115 plci->ncpi_state = 0;
7116 if ((ncci_state == OUTG_REJ_PENDING)
7117 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7118 {
7119 sig_req(plci,HANGUP,0);
7120 send_req(plci);
7121 plci->State = OUTG_DIS_PENDING;
7122 }
7123 }
7124 break;
7125 case N_RESET:
7126 a->ncci_state[ncci] = INC_RES_PENDING;
7127 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7128 break;
7129 case N_RESET_ACK:
7130 a->ncci_state[ncci] = CONNECTED;
7131 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7132 break;
7133
7134 case N_UDATA:
7135 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7136 {
7137 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(plci->internal_ind_buffer)) & 3);
7138 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7139 plci->NL.R = plci->RData;
7140 plci->NL.RNum = 1;
7141 return;
7142 }
7143 case N_BDATA:
7144 case N_DATA:
7145 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7146 || (a->ncci_state[ncci] == IDLE)
7147 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7148 {
7149 plci->NL.RNR = 2;
7150 break;
7151 }
7152 if ((a->ncci_state[ncci] != CONNECTED)
7153 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7154 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7155 {
7156 dbug(1,dprintf("flow control"));
7157 plci->NL.RNR = 1; /* flow control */
7158 channel_x_off (plci, ch, 0);
7159 break;
7160 }
7161
7162 NCCIcode = ncci | (((word)a->Id) << 8);
7163
7164 /* count all buffers within the Application pool */
7165 /* belonging to the same NCCI. If this is below the */
7166 /* number of buffers available per NCCI we accept */
7167 /* this packet, otherwise we reject it */
7168 count = 0;
7169 Num = 0xffff;
7170 for(i=0; i<APPLptr->MaxBuffer; i++) {
7171 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7172 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7173 }
7174
7175 if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7176 {
7177 dbug(3,dprintf("Flow-Control"));
7178 plci->NL.RNR = 1;
7179 if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7180 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7181 {
7182 plci->NL.RNR = 2;
7183 dbug(3,dprintf("DiscardData"));
7184 } else {
7185 channel_x_off (plci, ch, 0);
7186 }
7187 break;
7188 }
7189 else
7190 {
7191 APPLptr->NCCIDataFlowCtrlTimer = 0;
7192 }
7193
7194 plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7195 if(!plci->RData[0].P) {
7196 plci->NL.RNR = 1;
7197 channel_x_off (plci, ch, 0);
7198 break;
7199 }
7200
7201 APPLptr->DataNCCI[Num] = NCCIcode;
7202 APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7203 dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7204
7205 plci->RNum = Num;
7206 plci->RFlags = plci->NL.Ind>>4;
7207 plci->RData[0].PLength = APPLptr->MaxDataLength;
7208 plci->NL.R = plci->RData;
7209 if ((plci->NL.RLength != 0)
7210 && ((plci->B2_prot == B2_V120_ASYNC)
7211 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7212 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7213 {
7214 plci->RData[1].P = plci->RData[0].P;
7215 plci->RData[1].PLength = plci->RData[0].PLength;
7216 plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
7217 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7218 plci->RData[0].PLength = 1;
7219 else
7220 plci->RData[0].PLength = 2;
7221 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7222 plci->RFlags |= 0x0010;
7223 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7224 plci->RFlags |= 0x8000;
7225 plci->NL.RNum = 2;
7226 }
7227 else
7228 {
7229 if((plci->NL.Ind &0x0f)==N_UDATA)
7230 plci->RFlags |= 0x0010;
7231
7232 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7233 plci->RFlags |= 0x0001;
7234
7235 plci->NL.RNum = 1;
7236 }
7237 break;
7238 case N_DATA_ACK:
7239 data_ack (plci, ch);
7240 break;
7241 default:
7242 plci->NL.RNR = 2;
7243 break;
7244 }
7245}
7246
7247/*------------------------------------------------------------------*/
7248/* find a free PLCI */
7249/*------------------------------------------------------------------*/
7250
7251word get_plci(DIVA_CAPI_ADAPTER * a)
7252{
7253 word i,j;
7254 PLCI * plci;
7255
7256 dump_plcis (a);
7257 for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7258 if(i==a->max_plci) {
7259 dbug(1,dprintf("get_plci: out of PLCIs"));
7260 return 0;
7261 }
7262 plci = &a->plci[i];
7263 plci->Id = (byte)(i+1);
7264
7265 plci->Sig.Id = 0;
7266 plci->NL.Id = 0;
7267 plci->sig_req = 0;
7268 plci->nl_req = 0;
7269
7270 plci->appl = NULL;
7271 plci->relatedPTYPLCI = NULL;
7272 plci->State = IDLE;
7273 plci->SuppState = IDLE;
7274 plci->channels = 0;
7275 plci->tel = 0;
7276 plci->B1_resource = 0;
7277 plci->B2_prot = 0;
7278 plci->B3_prot = 0;
7279
7280 plci->command = 0;
7281 plci->m_command = 0;
7282 init_internal_command_queue (plci);
7283 plci->number = 0;
7284 plci->req_in_start = 0;
7285 plci->req_in = 0;
7286 plci->req_out = 0;
7287 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7288 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7289 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7290
7291 plci->data_sent = FALSE;
7292 plci->send_disc = 0;
7293 plci->sig_global_req = 0;
7294 plci->sig_remove_id = 0;
7295 plci->nl_global_req = 0;
7296 plci->nl_remove_id = 0;
7297 plci->adv_nl = 0;
7298 plci->manufacturer = FALSE;
7299 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7300 plci->spoofed_msg = 0;
7301 plci->ptyState = 0;
7302 plci->cr_enquiry = FALSE;
7303 plci->hangup_flow_ctrl_timer = 0;
7304
7305 plci->ncci_ring_list = 0;
7306 for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7307 clear_c_ind_mask (plci);
7308 set_group_ind_mask (plci);
7309 plci->fax_connect_info_length = 0;
7310 plci->nsf_control_bits = 0;
7311 plci->ncpi_state = 0x00;
7312 plci->ncpi_buffer[0] = 0;
7313
7314 plci->requested_options_conn = 0;
7315 plci->requested_options = 0;
7316 plci->notifiedcall = 0;
7317 plci->vswitchstate = 0;
7318 plci->vsprot = 0;
7319 plci->vsprotdialect = 0;
7320 init_b1_config (plci);
7321 dbug(1,dprintf("get_plci(%x)",plci->Id));
7322 return i+1;
7323}
7324
7325/*------------------------------------------------------------------*/
7326/* put a parameter in the parameter buffer */
7327/*------------------------------------------------------------------*/
7328
7329static void add_p(PLCI * plci, byte code, byte * p)
7330{
7331 word p_length;
7332
7333 p_length = 0;
7334 if(p) p_length = p[0];
7335 add_ie(plci, code, p, p_length);
7336}
7337
7338/*------------------------------------------------------------------*/
7339/* put a structure in the parameter buffer */
7340/*------------------------------------------------------------------*/
7341static void add_s(PLCI * plci, byte code, API_PARSE * p)
7342{
7343 if(p) add_ie(plci, code, p->info, (word)p->length);
7344}
7345
7346/*------------------------------------------------------------------*/
7347/* put multiple structures in the parameter buffer */
7348/*------------------------------------------------------------------*/
7349static void add_ss(PLCI * plci, byte code, API_PARSE * p)
7350{
7351 byte i;
7352
7353 if(p){
7354 dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7355 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7356 dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7357 add_ie(plci, p->info[i-1], (byte *)&(p->info[i]), (word)p->info[i]);
7358 }
7359 }
7360}
7361
7362/*------------------------------------------------------------------*/
7363/* return the channel number sent by the application in a esc_chi */
7364/*------------------------------------------------------------------*/
7365static byte getChannel(API_PARSE * p)
7366{
7367 byte i;
7368
7369 if(p){
7370 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7371 if(p->info[i]==2){
7372 if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7373 }
7374 }
7375 }
7376 return 0;
7377}
7378
7379
7380/*------------------------------------------------------------------*/
7381/* put an information element in the parameter buffer */
7382/*------------------------------------------------------------------*/
7383
7384static void add_ie(PLCI * plci, byte code, byte * p, word p_length)
7385{
7386 word i;
7387
7388 if(!(code &0x80) && !p_length) return;
7389
7390 if(plci->req_in==plci->req_in_start) {
7391 plci->req_in +=2;
7392 }
7393 else {
7394 plci->req_in--;
7395 }
7396 plci->RBuffer[plci->req_in++] = code;
7397
7398 if(p) {
7399 plci->RBuffer[plci->req_in++] = (byte)p_length;
7400 for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7401 }
7402
7403 plci->RBuffer[plci->req_in++] = 0;
7404}
7405
7406/*------------------------------------------------------------------*/
7407/* put a unstructured data into the buffer */
7408/*------------------------------------------------------------------*/
7409
7410void add_d(PLCI * plci, word length, byte * p)
7411{
7412 word i;
7413
7414 if(plci->req_in==plci->req_in_start) {
7415 plci->req_in +=2;
7416 }
7417 else {
7418 plci->req_in--;
7419 }
7420 for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7421}
7422
7423/*------------------------------------------------------------------*/
7424/* put parameters from the Additional Info parameter in the */
7425/* parameter buffer */
7426/*------------------------------------------------------------------*/
7427
7428void add_ai(PLCI * plci, API_PARSE * ai)
7429{
7430 word i;
7431 API_PARSE ai_parms[5];
7432
7433 for(i=0;i<5;i++) ai_parms[i].length = 0;
7434
7435 if(!ai->length)
7436 return;
7437 if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7438 return;
7439
7440 add_s (plci,KEY,&ai_parms[1]);
7441 add_s (plci,UUI,&ai_parms[2]);
7442 add_ss(plci,FTY,&ai_parms[3]);
7443}
7444
7445/*------------------------------------------------------------------*/
7446/* put parameter for b1 protocol in the parameter buffer */
7447/*------------------------------------------------------------------*/
7448
7449word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_facilities)
7450{
7451 API_PARSE bp_parms[8];
7452 API_PARSE mdm_cfg[9];
7453 API_PARSE global_config[2];
7454 byte cai[256];
7455 byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7456 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7457 word i;
7458
7459 API_PARSE mdm_cfg_v18[4];
7460 word j, n, w;
7461 dword d;
7462
7463
7464 for(i=0;i<8;i++) bp_parms[i].length = 0;
7465 for(i=0;i<2;i++) global_config[i].length = 0;
7466
7467 dbug(1,dprintf("add_b1"));
7468 api_save_msg(bp, "s", &plci->B_protocol);
7469
7470 if(b_channel_info==2){
7471 plci->B1_resource = 0;
7472 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7473 add_p(plci, CAI, "\x01\x00");
7474 dbug(1,dprintf("Cai=1,0 (no resource)"));
7475 return 0;
7476 }
7477
7478 if(plci->tel == CODEC_PERMANENT) return 0;
7479 else if(plci->tel == CODEC){
7480 plci->B1_resource = 1;
7481 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7482 add_p(plci, CAI, "\x01\x01");
7483 dbug(1,dprintf("Cai=1,1 (Codec)"));
7484 return 0;
7485 }
7486 else if(plci->tel == ADV_VOICE){
7487 plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7488 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7489 voice_cai[1] = plci->B1_resource;
7490 PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7491 add_p(plci, CAI, voice_cai);
7492 dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7493 return 0;
7494 }
7495 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7496 if (plci->call_dir & CALL_DIR_OUT)
7497 plci->call_dir |= CALL_DIR_ORIGINATE;
7498 else if (plci->call_dir & CALL_DIR_IN)
7499 plci->call_dir |= CALL_DIR_ANSWER;
7500
7501 if(!bp->length){
7502 plci->B1_resource = 0x5;
7503 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7504 add_p(plci, CAI, "\x01\x05");
7505 return 0;
7506 }
7507
7508 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7509 if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7510 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7511 {
7512 bp_parms[6].length = 0;
7513 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7514 {
7515 dbug(1,dprintf("b-form.!"));
7516 return _WRONG_MESSAGE_FORMAT;
7517 }
7518 }
7519 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7520 {
7521 dbug(1,dprintf("b-form.!"));
7522 return _WRONG_MESSAGE_FORMAT;
7523 }
7524
7525 if(bp_parms[6].length)
7526 {
7527 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7528 {
7529 return _WRONG_MESSAGE_FORMAT;
7530 }
7531 switch(GET_WORD(global_config[0].info))
7532 {
7533 case 1:
7534 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7535 break;
7536 case 2:
7537 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7538 break;
7539 }
7540 }
7541 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7542
7543
7544 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7545 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7546 {
7547 plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7548 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7549 cai[1] = plci->B1_resource;
7550 cai[2] = 0;
7551 cai[3] = 0;
7552 cai[4] = 0;
7553 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7554 for (i = 0; i < bp_parms[3].length; i++)
7555 cai[7+i] = bp_parms[3].info[1+i];
7556 cai[0] = 6 + bp_parms[3].length;
7557 add_p(plci, CAI, cai);
7558 return 0;
7559 }
7560
7561
7562 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7563 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7564 {
7565 plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7566 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7567 cai[1] = plci->B1_resource;
7568 cai[2] = 0;
7569 cai[3] = 0;
7570 cai[4] = 0;
7571 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7572 cai[0] = 6;
7573 add_p(plci, CAI, cai);
7574 return 0;
7575 }
7576
7577
7578 if ((GET_WORD(bp_parms[0].info) >= 32)
7579 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7580 && ((GET_WORD(bp_parms[0].info) != 3)
7581 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7582 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7583 {
7584 return _B1_NOT_SUPPORTED;
7585 }
7586 plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7587 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7588 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7589 cai[0] = 6;
7590 cai[1] = plci->B1_resource;
7591 for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7592
7593 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7594 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7595 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7596 { /* B1 - modem */
7597 for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7598
7599 if (bp_parms[3].length)
7600 {
7601 if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7602 {
7603 return (_WRONG_MESSAGE_FORMAT);
7604 }
7605
7606 cai[2] = 0; /* Bit rate for adaptation */
7607
7608 dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7609
7610 PUT_WORD (&cai[13], 0); /* Min Tx speed */
7611 PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7612 PUT_WORD (&cai[17], 0); /* Min Rx speed */
7613 PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7614
7615 cai[3] = 0; /* Async framing parameters */
7616 switch (GET_WORD (mdm_cfg[2].info))
7617 { /* Parity */
7618 case 1: /* odd parity */
7619 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7620 dbug(1,dprintf("MDM: odd parity"));
7621 break;
7622
7623 case 2: /* even parity */
7624 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7625 dbug(1,dprintf("MDM: even parity"));
7626 break;
7627
7628 default:
7629 dbug(1,dprintf("MDM: no parity"));
7630 break;
7631 }
7632
7633 switch (GET_WORD (mdm_cfg[3].info))
7634 { /* stop bits */
7635 case 1: /* 2 stop bits */
7636 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7637 dbug(1,dprintf("MDM: 2 stop bits"));
7638 break;
7639
7640 default:
7641 dbug(1,dprintf("MDM: 1 stop bit"));
7642 break;
7643 }
7644
7645 switch (GET_WORD (mdm_cfg[1].info))
7646 { /* char length */
7647 case 5:
7648 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7649 dbug(1,dprintf("MDM: 5 bits"));
7650 break;
7651
7652 case 6:
7653 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7654 dbug(1,dprintf("MDM: 6 bits"));
7655 break;
7656
7657 case 7:
7658 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7659 dbug(1,dprintf("MDM: 7 bits"));
7660 break;
7661
7662 default:
7663 dbug(1,dprintf("MDM: 8 bits"));
7664 break;
7665 }
7666
7667 cai[7] = 0; /* Line taking options */
7668 cai[8] = 0; /* Modulation negotiation options */
7669 cai[9] = 0; /* Modulation options */
7670
7671 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7672 {
7673 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7674 dbug(1, dprintf("MDM: Reverse direction"));
7675 }
7676
7677 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7678 {
7679 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7680 dbug(1, dprintf("MDM: Disable retrain"));
7681 }
7682
7683 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7684 {
7685 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7686 dbug(1, dprintf("MDM: Disable ring tone"));
7687 }
7688
7689 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7690 {
7691 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7692 dbug(1, dprintf("MDM: 1800 guard tone"));
7693 }
7694 else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7695 {
7696 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7697 dbug(1, dprintf("MDM: 550 guard tone"));
7698 }
7699
7700 if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7701 {
7702 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7703 dbug(1, dprintf("MDM: V100"));
7704 }
7705 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7706 {
7707 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7708 dbug(1, dprintf("MDM: IN CLASS"));
7709 }
7710 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7711 {
7712 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7713 dbug(1, dprintf("MDM: DISABLED"));
7714 }
7715 cai[0] = 20;
7716
7717 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7718 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7719 {
7720 plci->requested_options |= 1L << PRIVATE_V18;
7721 }
7722 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7723 plci->requested_options |= 1L << PRIVATE_VOWN;
7724
7725 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7726 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7727 {
7728 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7729 {
7730 i = 27;
7731 if (mdm_cfg[6].length >= 4)
7732 {
7733 d = GET_DWORD(&mdm_cfg[6].info[1]);
7734 cai[7] |= (byte) d; /* line taking options */
7735 cai[9] |= (byte)(d >> 8); /* modulation options */
7736 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7737 cai[++i] = (byte)(d >> 24);
7738 if (mdm_cfg[6].length >= 8)
7739 {
7740 d = GET_DWORD(&mdm_cfg[6].info[5]);
7741 cai[10] |= (byte) d; /* disabled modulations mask */
7742 cai[11] |= (byte)(d >> 8);
7743 if (mdm_cfg[6].length >= 12)
7744 {
7745 d = GET_DWORD(&mdm_cfg[6].info[9]);
7746 cai[12] = (byte) d; /* enabled modulations mask */
7747 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7748 cai[++i] = (byte)(d >> 16);
7749 cai[++i] = (byte)(d >> 24);
7750 cai[++i] = 0;
7751 if (mdm_cfg[6].length >= 14)
7752 {
7753 w = GET_WORD(&mdm_cfg[6].info[13]);
7754 if (w != 0)
7755 PUT_WORD(&cai[13], w); /* min tx speed */
7756 if (mdm_cfg[6].length >= 16)
7757 {
7758 w = GET_WORD(&mdm_cfg[6].info[15]);
7759 if (w != 0)
7760 PUT_WORD(&cai[15], w); /* max tx speed */
7761 if (mdm_cfg[6].length >= 18)
7762 {
7763 w = GET_WORD(&mdm_cfg[6].info[17]);
7764 if (w != 0)
7765 PUT_WORD(&cai[17], w); /* min rx speed */
7766 if (mdm_cfg[6].length >= 20)
7767 {
7768 w = GET_WORD(&mdm_cfg[6].info[19]);
7769 if (w != 0)
7770 PUT_WORD(&cai[19], w); /* max rx speed */
7771 if (mdm_cfg[6].length >= 22)
7772 {
7773 w = GET_WORD(&mdm_cfg[6].info[21]);
7774 cai[23] = (byte)(-((short) w)); /* transmit level */
7775 if (mdm_cfg[6].length >= 24)
7776 {
7777 w = GET_WORD(&mdm_cfg[6].info[23]);
7778 cai[22] |= (byte) w; /* info options mask */
7779 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7780 }
7781 }
7782 }
7783 }
7784 }
7785 }
7786 }
7787 }
7788 }
7789 cai[27] = i - 27;
7790 i++;
7791 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7792 {
7793 if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7794 {
7795 for (n = 0; n < 3; n++)
7796 {
7797 cai[i] = (byte)(mdm_cfg_v18[n].length);
7798 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7799 cai[i+j] = mdm_cfg_v18[n].info[j];
7800 i += cai[i] + 1;
7801 }
7802 }
7803 }
7804 cai[0] = (byte)(i - 1);
7805 }
7806 }
7807
7808 }
7809 }
7810 if(GET_WORD(bp_parms[0].info)==2 || /* V.110 async */
7811 GET_WORD(bp_parms[0].info)==3 ) /* V.110 sync */
7812 {
7813 if(bp_parms[3].length){
7814 dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7815 switch(GET_WORD(&bp_parms[3].info[1])){ /* Rate */
7816 case 0:
7817 case 56000:
7818 if(GET_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */
7819 dbug(1,dprintf("56k sync HSCX"));
7820 cai[1] = 8;
7821 cai[2] = 0;
7822 cai[3] = 0;
7823 }
7824 else if(GET_WORD(bp_parms[0].info)==2){
7825 dbug(1,dprintf("56k async DSP"));
7826 cai[2] = 9;
7827 }
7828 break;
7829 case 50: cai[2] = 1; break;
7830 case 75: cai[2] = 1; break;
7831 case 110: cai[2] = 1; break;
7832 case 150: cai[2] = 1; break;
7833 case 200: cai[2] = 1; break;
7834 case 300: cai[2] = 1; break;
7835 case 600: cai[2] = 1; break;
7836 case 1200: cai[2] = 2; break;
7837 case 2400: cai[2] = 3; break;
7838 case 4800: cai[2] = 4; break;
7839 case 7200: cai[2] = 10; break;
7840 case 9600: cai[2] = 5; break;
7841 case 12000: cai[2] = 13; break;
7842 case 24000: cai[2] = 0; break;
7843 case 14400: cai[2] = 11; break;
7844 case 19200: cai[2] = 6; break;
7845 case 28800: cai[2] = 12; break;
7846 case 38400: cai[2] = 7; break;
7847 case 48000: cai[2] = 8; break;
7848 case 76: cai[2] = 15; break; /* 75/1200 */
7849 case 1201: cai[2] = 14; break; /* 1200/75 */
7850 case 56001: cai[2] = 9; break; /* V.110 56000 */
7851
7852 default:
7853 return _B1_PARM_NOT_SUPPORTED;
7854 }
7855 cai[3] = 0;
7856 if (cai[1] == 13) /* v.110 async */
7857 {
7858 if (bp_parms[3].length >= 8)
7859 {
7860 switch (GET_WORD (&bp_parms[3].info[3]))
7861 { /* char length */
7862 case 5:
7863 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7864 break;
7865 case 6:
7866 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7867 break;
7868 case 7:
7869 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7870 break;
7871 }
7872 switch (GET_WORD (&bp_parms[3].info[5]))
7873 { /* Parity */
7874 case 1: /* odd parity */
7875 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7876 break;
7877 case 2: /* even parity */
7878 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7879 break;
7880 }
7881 switch (GET_WORD (&bp_parms[3].info[7]))
7882 { /* stop bits */
7883 case 1: /* 2 stop bits */
7884 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7885 break;
7886 }
7887 }
7888 }
7889 }
7890 else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7891 dbug(1,dprintf("V.110 default 56k sync"));
7892 cai[1] = 8;
7893 cai[2] = 0;
7894 cai[3] = 0;
7895 }
7896 else {
7897 dbug(1,dprintf("V.110 default 9600 async"));
7898 cai[2] = 5;
7899 }
7900 }
7901 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7902 dbug(1,dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6]));
7903/* HexDump ("CAI", sizeof(cai), &cai[0]); */
7904
7905 add_p(plci, CAI, cai);
7906 return 0;
7907}
7908
7909/*------------------------------------------------------------------*/
7910/* put parameter for b2 and B3 protocol in the parameter buffer */
7911/*------------------------------------------------------------------*/
7912
7913word add_b23(PLCI * plci, API_PARSE * bp)
7914{
7915 word i, fax_control_bits;
7916 byte pos, len;
7917 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7918 API_PARSE bp_parms[8];
7919 API_PARSE * b1_config;
7920 API_PARSE * b2_config;
7921 API_PARSE b2_config_parms[8];
7922 API_PARSE * b3_config;
7923 API_PARSE b3_config_parms[6];
7924 API_PARSE global_config[2];
7925
7926 static byte llc[3] = {2,0,0};
7927 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7928 static byte nlc[256];
7929 static byte lli[12] = {1,1};
7930
7931 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7932 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7933
7934 const byte llc3[] = {4,3,2,2,6,6,0};
7935 const byte header[] = {0,2,3,3,0,0,0};
7936
7937 for(i=0;i<8;i++) bp_parms[i].length = 0;
7938 for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7939 for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7940
7941 lli[0] = 1;
7942 lli[1] = 1;
7943 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7944 lli[1] |= 2;
7945 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7946 lli[1] |= 4;
7947
7948 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7949 lli[1] |= 0x10;
7950 if (plci->rx_dma_descriptor <= 0) {
7951 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7952 if (plci->rx_dma_descriptor >= 0)
7953 plci->rx_dma_descriptor++;
7954 }
7955 if (plci->rx_dma_descriptor > 0) {
7956 lli[0] = 6;
7957 lli[1] |= 0x40;
7958 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7959 lli[3] = (byte)plci->rx_dma_magic;
7960 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7961 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7962 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7963 }
7964 }
7965
7966 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7967 lli[1] |= 0x20;
7968 }
7969
7970 dbug(1,dprintf("add_b23"));
7971 api_save_msg(bp, "s", &plci->B_protocol);
7972
7973 if(!bp->length && plci->tel)
7974 {
7975 plci->adv_nl = TRUE;
7976 dbug(1,dprintf("Default adv.Nl"));
7977 add_p(plci,LLI,lli);
7978 plci->B2_prot = 1 /*XPARENT*/;
7979 plci->B3_prot = 0 /*XPARENT*/;
7980 llc[1] = 2;
7981 llc[2] = 4;
7982 add_p(plci, LLC, llc);
7983 dlc[0] = 2;
7984 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
7985 add_p(plci, DLC, dlc);
7986 return 0;
7987 }
7988
7989 if(!bp->length) /*default*/
7990 {
7991 dbug(1,dprintf("ret default"));
7992 add_p(plci,LLI,lli);
7993 plci->B2_prot = 0 /*X.75 */;
7994 plci->B3_prot = 0 /*XPARENT*/;
7995 llc[1] = 1;
7996 llc[2] = 4;
7997 add_p(plci, LLC, llc);
7998 dlc[0] = 2;
7999 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8000 add_p(plci, DLC, dlc);
8001 return 0;
8002 }
8003 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8004 if((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8005
8006 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8007 {
8008 bp_parms[6].length = 0;
8009 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8010 {
8011 dbug(1,dprintf("b-form.!"));
8012 return _WRONG_MESSAGE_FORMAT;
8013 }
8014 }
8015 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8016 {
8017 dbug(1,dprintf("b-form.!"));
8018 return _WRONG_MESSAGE_FORMAT;
8019 }
8020
8021 if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8022 {
8023 if(GET_WORD(bp_parms[1].info)!=1
8024 || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
8025 plci->adv_nl = TRUE;
8026 }
8027 else if(plci->tel) return _B2_NOT_SUPPORTED;
8028
8029
8030 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8031 && (GET_WORD(bp_parms[2].info) == B3_RTP)
8032 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8033 {
8034 add_p(plci,LLI,lli);
8035 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8036 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8037 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8038 llc[2] = 4;
8039 add_p(plci, LLC, llc);
8040 dlc[0] = 2;
8041 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8042 dlc[3] = 3; /* Addr A */
8043 dlc[4] = 1; /* Addr B */
8044 dlc[5] = 7; /* modulo mode */
8045 dlc[6] = 7; /* window size */
8046 dlc[7] = 0; /* XID len Lo */
8047 dlc[8] = 0; /* XID len Hi */
8048 for (i = 0; i < bp_parms[4].length; i++)
8049 dlc[9+i] = bp_parms[4].info[1+i];
8050 dlc[0] = (byte)(8 + bp_parms[4].length);
8051 add_p(plci, DLC, dlc);
8052 for (i = 0; i < bp_parms[5].length; i++)
8053 nlc[1+i] = bp_parms[5].info[1+i];
8054 nlc[0] = (byte)(bp_parms[5].length);
8055 add_p(plci, NLC, nlc);
8056 return 0;
8057 }
8058
8059
8060
8061 if ((GET_WORD(bp_parms[1].info) >= 32)
8062 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8063 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8064 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8065
8066 {
8067 return _B2_NOT_SUPPORTED;
8068 }
8069 if ((GET_WORD(bp_parms[2].info) >= 32)
8070 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8071 {
8072 return _B3_NOT_SUPPORTED;
8073 }
8074 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8075 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8076 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8077 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8078 {
8079 return (add_modem_b23 (plci, bp_parms));
8080 }
8081
8082 add_p(plci,LLI,lli);
8083
8084 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8085 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8086 if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8087
8088 if(bp_parms[6].length)
8089 {
8090 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8091 {
8092 return _WRONG_MESSAGE_FORMAT;
8093 }
8094 switch(GET_WORD(global_config[0].info))
8095 {
8096 case 1:
8097 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8098 break;
8099 case 2:
8100 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8101 break;
8102 }
8103 }
8104 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8105
8106
8107 if (plci->B2_prot == B2_PIAFS)
8108 llc[1] = PIAFS_CRC;
8109 else
8110/* IMPLEMENT_PIAFS */
8111 {
8112 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8113 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8114 }
8115 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8116
8117 add_p(plci, LLC, llc);
8118
8119 dlc[0] = 2;
8120 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8121 header[GET_WORD(bp_parms[2].info)]);
8122
8123 b1_config = &bp_parms[3];
8124 nlc[0] = 0;
8125 if(plci->B3_prot == 4
8126 || plci->B3_prot == 5)
8127 {
8128 for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8129 nlc[0] = sizeof(T30_INFO);
8130 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8131 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8132 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8133 if(b1_config->length>=2)
8134 {
8135 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8136 }
8137 }
8138 b2_config = &bp_parms[4];
8139
8140
8141 if (llc[1] == PIAFS_CRC)
8142 {
8143 if (plci->B3_prot != B3_TRANSPARENT)
8144 {
8145 return _B_STACK_NOT_SUPPORTED;
8146 }
8147 if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8148 return _WRONG_MESSAGE_FORMAT;
8149 }
8150 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8151 dlc[3] = 0; /* Addr A */
8152 dlc[4] = 0; /* Addr B */
8153 dlc[5] = 0; /* modulo mode */
8154 dlc[6] = 0; /* window size */
8155 if (b2_config->length >= 7){
8156 dlc[ 7] = 7;
8157 dlc[ 8] = 0;
8158 dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8159 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8160 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8161 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8162 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8163 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8164 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8165 dlc[ 0] = 15;
8166 if(b2_config->length >= 8) { /* PIAFS control abilities */
8167 dlc[ 7] = 10;
8168 dlc[16] = 2; /* Length of PIAFS extention */
8169 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8170 dlc[18] = b2_config_parms[4].info[0]; /* value */
8171 dlc[ 0] = 18;
8172 }
8173 }
8174 else /* default values, 64K, variable, no compression */
8175 {
8176 dlc[ 7] = 7;
8177 dlc[ 8] = 0;
8178 dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8179 dlc[10] = 0x03; /* V.42bis P0 */
8180 dlc[11] = 0; /* V.42bis P0 */
8181 dlc[12] = 0; /* V.42bis P1 */
8182 dlc[13] = 0; /* V.42bis P1 */
8183 dlc[14] = 0; /* V.42bis P2 */
8184 dlc[15] = 0; /* V.42bis P2 */
8185 dlc[ 0] = 15;
8186 }
8187 add_p(plci, DLC, dlc);
8188 }
8189 else
8190
8191 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8192 {
8193 if (plci->B3_prot != B3_TRANSPARENT)
8194 return _B_STACK_NOT_SUPPORTED;
8195
8196 dlc[0] = 6;
8197 PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8198 dlc[3] = 0x08;
8199 dlc[4] = 0x01;
8200 dlc[5] = 127;
8201 dlc[6] = 7;
8202 if (b2_config->length != 0)
8203 {
8204 if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8205 return _WRONG_MESSAGE_FORMAT;
8206 }
8207 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8208 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8209 if (b2_config->info[3] != 128)
8210 {
8211 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8212 return _B2_PARM_NOT_SUPPORTED;
8213 }
8214 dlc[5] = (byte)(b2_config->info[3] - 1);
8215 dlc[6] = b2_config->info[4];
8216 if(llc[1]==V120_V42BIS){
8217 if (b2_config->length >= 10){
8218 dlc[ 7] = 6;
8219 dlc[ 8] = 0;
8220 dlc[ 9] = b2_config_parms[4].info[0];
8221 dlc[10] = b2_config_parms[4].info[1];
8222 dlc[11] = b2_config_parms[5].info[0];
8223 dlc[12] = b2_config_parms[5].info[1];
8224 dlc[13] = b2_config_parms[6].info[0];
8225 dlc[14] = b2_config_parms[6].info[1];
8226 dlc[ 0] = 14;
8227 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8228 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8229 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8230 }
8231 else {
8232 dlc[ 6] = 14;
8233 }
8234 }
8235 }
8236 }
8237 else
8238 {
8239 if(b2_config->length)
8240 {
8241 dbug(1,dprintf("B2-Config"));
8242 if(llc[1]==X75_V42BIS){
8243 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8244 {
8245 return _WRONG_MESSAGE_FORMAT;
8246 }
8247 }
8248 else {
8249 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8250 {
8251 return _WRONG_MESSAGE_FORMAT;
8252 }
8253 }
8254 /* if B2 Protocol is LAPD, b2_config structure is different */
8255 if(llc[1]==6)
8256 {
8257 dlc[0] = 4;
8258 if(b2_config->length>=1) dlc[2] = b2_config->info[1]; /* TEI */
8259 else dlc[2] = 0x01;
8260 if( (b2_config->length>=2) && (plci->B2_prot==12) )
8261 {
8262 SAPI = b2_config->info[2]; /* SAPI */
8263 }
8264 dlc[1] = SAPI;
8265 if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8266 {
8267 dlc[3] = 127; /* Mode */
8268 }
8269 else
8270 {
8271 dlc[3] = 7; /* Mode */
8272 }
8273
8274 if(b2_config->length>=4) dlc[4] = b2_config->info[4]; /* Window */
8275 else dlc[4] = 1;
8276 dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8277 if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8278 }
8279 else
8280 {
8281 dlc[0] = (byte)(b2_config_parms[4].length+6);
8282 dlc[3] = b2_config->info[1];
8283 dlc[4] = b2_config->info[2];
8284 if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8285 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8286 return _B2_PARM_NOT_SUPPORTED;
8287 }
8288
8289 dlc[5] = (byte)(b2_config->info[3]-1);
8290 dlc[6] = b2_config->info[4];
8291 if(dlc[6]>dlc[5]){
8292 dbug(1,dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6]));
8293 return _B2_PARM_NOT_SUPPORTED;
8294 }
8295
8296 if(llc[1]==X75_V42BIS) {
8297 if (b2_config->length >= 10){
8298 dlc[ 7] = 6;
8299 dlc[ 8] = 0;
8300 dlc[ 9] = b2_config_parms[4].info[0];
8301 dlc[10] = b2_config_parms[4].info[1];
8302 dlc[11] = b2_config_parms[5].info[0];
8303 dlc[12] = b2_config_parms[5].info[1];
8304 dlc[13] = b2_config_parms[6].info[0];
8305 dlc[14] = b2_config_parms[6].info[1];
8306 dlc[ 0] = 14;
8307 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8308 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8309 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8310 }
8311 else {
8312 dlc[ 6] = 14;
8313 }
8314
8315 }
8316 else {
8317 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8318 for(i=0; i<b2_config_parms[4].length; i++)
8319 dlc[11+i] = b2_config_parms[4].info[1+i];
8320 }
8321 }
8322 }
8323 }
8324 add_p(plci, DLC, dlc);
8325
8326 b3_config = &bp_parms[5];
8327 if(b3_config->length)
8328 {
8329 if(plci->B3_prot == 4
8330 || plci->B3_prot == 5)
8331 {
8332 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8333 {
8334 return _WRONG_MESSAGE_FORMAT;
8335 }
8336 i = GET_WORD((byte *)(b3_config_parms[0].info));
8337 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8338 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8339 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8340 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8341 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8342 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8343 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8344 {
8345
8346 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8347 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8348 {
8349 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8350 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8351 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8352 }
8353
8354 ((T30_INFO *)&nlc[1])->recording_properties =
8355 T30_RECORDING_WIDTH_ISO_A3 |
8356 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8357 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8358 }
8359 if(plci->B3_prot == 5)
8360 {
8361 if (i & 0x0002) /* Accept incoming fax-polling requests */
8362 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8363 if (i & 0x2000) /* Do not use MR compression */
8364 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8365 if (i & 0x4000) /* Do not use MMR compression */
8366 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8367 if (i & 0x8000) /* Do not use ECM */
8368 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8369 if (plci->fax_connect_info_length != 0)
8370 {
8371 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8372 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8373 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8374 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8375 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8376 }
8377 }
8378 /* copy station id to NLC */
8379 for(i=0; i<20; i++)
8380 {
8381 if(i<b3_config_parms[2].length)
8382 {
8383 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1+i];
8384 }
8385 else
8386 {
8387 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8388 }
8389 }
8390 ((T30_INFO *)&nlc[1])->station_id_len = 20;
8391 /* copy head line to NLC */
8392 if(b3_config_parms[3].length)
8393 {
8394
8395 pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8396 if (pos != 0)
8397 {
8398 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8399 pos = 0;
8400 else
8401 {
8402 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8403 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8404 len = (byte)b3_config_parms[2].length;
8405 if (len > 20)
8406 len = 20;
8407 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8408 {
8409 for (i = 0; i < len; i++)
8410 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[2].info)[1+i];
8411 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8412 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8413 }
8414 }
8415 }
8416
8417 len = (byte)b3_config_parms[3].length;
8418 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8419 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8420 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8421 nlc[0] += (byte)(pos + len);
8422 for (i = 0; i < len; i++)
8423 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[3].info)[1+i];
8424 }
8425 else
8426 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8427
8428 plci->nsf_control_bits = 0;
8429 if(plci->B3_prot == 5)
8430 {
8431 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8432 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8433 {
8434 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8435 }
8436 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8437 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8438 {
8439 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8440 }
8441 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8442 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8443 {
8444 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8445 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8446 {
8447 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8448 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8449 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8450 }
8451 len = nlc[0];
8452 pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
8453 if (pos < plci->fax_connect_info_length)
8454 {
8455 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8456 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8457 }
8458 else
8459 nlc[++len] = 0;
8460 if (pos < plci->fax_connect_info_length)
8461 {
8462 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8463 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8464 }
8465 else
8466 nlc[++len] = 0;
8467 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8468 & (1L << PRIVATE_FAX_NONSTANDARD))
8469 {
8470 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8471 {
8472 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8473 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8474 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8475 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8476 }
8477 else
8478 {
8479 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8480 {
8481 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8482 nlc[++len] = 0;
8483 }
8484 else
8485 {
8486 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8487 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8488 nlc[++len] = (byte)(b3_config_parms[4].length);
8489 for (i = 0; i < b3_config_parms[4].length; i++)
8490 nlc[++len] = b3_config_parms[4].info[1+i];
8491 }
8492 }
8493 }
8494 nlc[0] = len;
8495 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8496 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8497 {
8498 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8499 }
8500 }
8501 }
8502
8503 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8504 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
8505 for (i = 0; i < len; i++)
8506 plci->fax_connect_info_buffer[i] = nlc[1+i];
8507 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8508 i += ((T30_INFO *)&nlc[1])->head_line_len;
8509 while (i < nlc[0])
8510 plci->fax_connect_info_buffer[len++] = nlc[++i];
8511 plci->fax_connect_info_length = len;
8512 }
8513 else
8514 {
8515 nlc[0] = 14;
8516 if(b3_config->length!=16)
8517 return _B3_PARM_NOT_SUPPORTED;
8518 for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8519 if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8520 return _B3_PARM_NOT_SUPPORTED;
8521 nlc[13] = b3_config->info[13];
8522 if(GET_WORD(&b3_config->info[15])>=nlc[13])
8523 return _B3_PARM_NOT_SUPPORTED;
8524 nlc[14] = b3_config->info[15];
8525 }
8526 }
8527 else
8528 {
8529 if (plci->B3_prot == 4
8530 || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8531 }
8532 add_p(plci, NLC, nlc);
8533 return 0;
8534}
8535
8536/*----------------------------------------------------------------*/
8537/* make the same as add_b23, but only for the modem related */
8538/* L2 and L3 B-Chan protocol. */
8539/* */
8540/* Enabled L2 and L3 Configurations: */
8541/* If L1 == Modem all negotiation */
8542/* only L2 == Modem with full negotiation is allowed */
8543/* If L1 == Modem async or sync */
8544/* only L2 == Transparent is allowed */
8545/* L3 == Modem or L3 == Transparent are allowed */
8546/* B2 Configuration for modem: */
8547/* word : enable/disable compression, bitoptions */
8548/* B3 Configuration for modem: */
8549/* empty */
8550/*----------------------------------------------------------------*/
8551static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms)
8552{
8553 static byte lli[12] = {1,1};
8554 static byte llc[3] = {2,0,0};
8555 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8556 API_PARSE mdm_config[2];
8557 word i;
8558 word b2_config = 0;
8559
8560 for(i=0;i<2;i++) mdm_config[i].length = 0;
8561 for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8562
8563 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8564 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8565 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8566 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8567 {
8568 return (_B_STACK_NOT_SUPPORTED);
8569 }
8570 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8571 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8572 {
8573 return (_B_STACK_NOT_SUPPORTED);
8574 }
8575
8576 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8577 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8578
8579 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8580 {
8581 if (api_parse (&bp_parms[4].info[1],
8582 (word)bp_parms[4].length, "w",
8583 mdm_config))
8584 {
8585 return (_WRONG_MESSAGE_FORMAT);
8586 }
8587 b2_config = GET_WORD(mdm_config[0].info);
8588 }
8589
8590 /* OK, L2 is modem */
8591
8592 lli[0] = 1;
8593 lli[1] = 1;
8594 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8595 lli[1] |= 2;
8596 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8597 lli[1] |= 4;
8598
8599 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8600 lli[1] |= 0x10;
8601 if (plci->rx_dma_descriptor <= 0) {
8602 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8603 if (plci->rx_dma_descriptor >= 0)
8604 plci->rx_dma_descriptor++;
8605 }
8606 if (plci->rx_dma_descriptor > 0) {
8607 lli[1] |= 0x40;
8608 lli[0] = 6;
8609 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8610 lli[3] = (byte)plci->rx_dma_magic;
8611 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8612 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8613 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8614 }
8615 }
8616
8617 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8618 lli[1] |= 0x20;
8619 }
8620
8621 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8622 /*V42*/ 10 : /*V42_IN*/ 9;
8623 llc[2] = 4; /* pass L3 always transparent */
8624 add_p(plci, LLI, lli);
8625 add_p(plci, LLC, llc);
8626 i = 1;
8627 PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8628 i += 2;
8629 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8630 {
8631 if (bp_parms[4].length)
8632 {
8633 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8634 dlc[i++] = 3; /* Addr A */
8635 dlc[i++] = 1; /* Addr B */
8636 dlc[i++] = 7; /* modulo mode */
8637 dlc[i++] = 7; /* window size */
8638 dlc[i++] = 0; /* XID len Lo */
8639 dlc[i++] = 0; /* XID len Hi */
8640
8641 if (b2_config & MDM_B2_DISABLE_V42bis)
8642 {
8643 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8644 }
8645 if (b2_config & MDM_B2_DISABLE_MNP)
8646 {
8647 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8648 }
8649 if (b2_config & MDM_B2_DISABLE_TRANS)
8650 {
8651 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8652 }
8653 if (b2_config & MDM_B2_DISABLE_V42)
8654 {
8655 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8656 }
8657 if (b2_config & MDM_B2_DISABLE_COMP)
8658 {
8659 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8660 }
8661 i++;
8662 }
8663 }
8664 else
8665 {
8666 dlc[i++] = 3; /* Addr A */
8667 dlc[i++] = 1; /* Addr B */
8668 dlc[i++] = 7; /* modulo mode */
8669 dlc[i++] = 7; /* window size */
8670 dlc[i++] = 0; /* XID len Lo */
8671 dlc[i++] = 0; /* XID len Hi */
8672 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8673 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8674 DLC_MODEMPROT_DISABLE_V42_DETECT |
8675 DLC_MODEMPROT_DISABLE_COMPRESSION;
8676 }
8677 dlc[0] = (byte)(i - 1);
8678/* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8679 add_p(plci, DLC, dlc);
8680 return (0);
8681}
8682
8683
8684/*------------------------------------------------------------------*/
8685/* send a request for the signaling entity */
8686/*------------------------------------------------------------------*/
8687
8688void sig_req(PLCI * plci, byte req, byte Id)
8689{
8690 if(!plci) return;
8691 if(plci->adapter->adapter_disabled) return;
8692 dbug(1,dprintf("sig_req(%x)",req));
8693 if (req == REMOVE)
8694 plci->sig_remove_id = plci->Sig.Id;
8695 if(plci->req_in==plci->req_in_start) {
8696 plci->req_in +=2;
8697 plci->RBuffer[plci->req_in++] = 0;
8698 }
8699 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8700 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8701 plci->RBuffer[plci->req_in++] = req; /* request */
8702 plci->RBuffer[plci->req_in++] = 0; /* channel */
8703 plci->req_in_start = plci->req_in;
8704}
8705
8706/*------------------------------------------------------------------*/
8707/* send a request for the network layer entity */
8708/*------------------------------------------------------------------*/
8709
8710void nl_req_ncci(PLCI * plci, byte req, byte ncci)
8711{
8712 if(!plci) return;
8713 if(plci->adapter->adapter_disabled) return;
8714 dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8715 if (req == REMOVE)
8716 {
8717 plci->nl_remove_id = plci->NL.Id;
8718 ncci_remove (plci, 0, (byte)(ncci != 0));
8719 ncci = 0;
8720 }
8721 if(plci->req_in==plci->req_in_start) {
8722 plci->req_in +=2;
8723 plci->RBuffer[plci->req_in++] = 0;
8724 }
8725 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8726 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8727 plci->RBuffer[plci->req_in++] = req; /* request */
8728 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8729 plci->req_in_start = plci->req_in;
8730}
8731
8732void send_req(PLCI * plci)
8733{
8734 ENTITY * e;
8735 word l;
8736/* word i; */
8737
8738 if(!plci) return;
8739 if(plci->adapter->adapter_disabled) return;
8740 channel_xmit_xon (plci);
8741
8742 /* if nothing to do, return */
8743 if(plci->req_in==plci->req_out) return;
8744 dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8745
8746 if(plci->nl_req || plci->sig_req) return;
8747
8748 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8749 plci->req_out += 2;
8750 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8751 plci->req_out += l;
8752 if(plci->RBuffer[plci->req_out]==1)
8753 {
8754 e = &plci->NL;
8755 plci->req_out++;
8756 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8757 e->ReqCh = plci->RBuffer[plci->req_out++];
8758 if(!(e->Id & 0x1f))
8759 {
8760 e->Id = NL_ID;
8761 plci->RBuffer[plci->req_out-4] = CAI;
8762 plci->RBuffer[plci->req_out-3] = 1;
8763 plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8764 plci->RBuffer[plci->req_out-1] = 0;
8765 l+=3;
8766 plci->nl_global_req = plci->nl_req;
8767 }
8768 dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8769 }
8770 else
8771 {
8772 e = &plci->Sig;
8773 if(plci->RBuffer[plci->req_out])
8774 e->Id = plci->RBuffer[plci->req_out];
8775 plci->req_out++;
8776 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8777 e->ReqCh = plci->RBuffer[plci->req_out++];
8778 if(!(e->Id & 0x1f))
8779 plci->sig_global_req = plci->sig_req;
8780 dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8781 }
8782 plci->XData[0].PLength = l;
8783 e->X = plci->XData;
8784 plci->adapter->request(e);
8785 dbug(1,dprintf("send_ok"));
8786}
8787
8788void send_data(PLCI * plci)
8789{
8790 DIVA_CAPI_ADAPTER * a;
8791 DATA_B3_DESC * data;
8792 NCCI *ncci_ptr;
8793 word ncci;
8794
8795 if (!plci->nl_req && plci->ncci_ring_list)
8796 {
8797 a = plci->adapter;
8798 ncci = plci->ncci_ring_list;
8799 do
8800 {
8801 ncci = a->ncci_next[ncci];
8802 ncci_ptr = &(a->ncci[ncci]);
8803 if (!(a->ncci_ch[ncci]
8804 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8805 {
8806 if (ncci_ptr->data_pending)
8807 {
8808 if ((a->ncci_state[ncci] == CONNECTED)
8809 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8810 || (plci->send_disc == ncci))
8811 {
8812 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8813 if ((plci->B2_prot == B2_V120_ASYNC)
8814 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8815 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8816 {
8817 plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8818 plci->NData[1].PLength = data->Length;
8819 if (data->Flags & 0x10)
8820 plci->NData[0].P = v120_break_header;
8821 else
8822 plci->NData[0].P = v120_default_header;
8823 plci->NData[0].PLength = 1 ;
8824 plci->NL.XNum = 2;
8825 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8826 }
8827 else
8828 {
8829 plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8830 plci->NData[0].PLength = data->Length;
8831 if (data->Flags & 0x10)
8832 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8833
8834 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8835 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8836
8837 else
8838 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8839 }
8840 plci->NL.X = plci->NData;
8841 plci->NL.ReqCh = a->ncci_ch[ncci];
8842 dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8843 plci->data_sent = TRUE;
8844 plci->data_sent_ptr = data->P;
8845 a->request(&plci->NL);
8846 }
8847 else {
8848 cleanup_ncci_data (plci, ncci);
8849 }
8850 }
8851 else if (plci->send_disc == ncci)
8852 {
8853 /* dprintf("N_DISC"); */
8854 plci->NData[0].PLength = 0;
8855 plci->NL.ReqCh = a->ncci_ch[ncci];
8856 plci->NL.Req = plci->nl_req = N_DISC;
8857 a->request(&plci->NL);
8858 plci->command = _DISCONNECT_B3_R;
8859 plci->send_disc = 0;
8860 }
8861 }
8862 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8863 plci->ncci_ring_list = ncci;
8864 }
8865}
8866
8867void listen_check(DIVA_CAPI_ADAPTER * a)
8868{
8869 word i,j;
8870 PLCI * plci;
8871 byte activnotifiedcalls = 0;
8872
8873 dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8874 if (!remove_started && !a->adapter_disabled)
8875 {
8876 for(i=0;i<a->max_plci;i++)
8877 {
8878 plci = &(a->plci[i]);
8879 if(plci->notifiedcall) activnotifiedcalls++;
8880 }
8881 dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8882
8883 for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8884 if((j=get_plci(a))) {
8885 a->listen_active++;
8886 plci = &a->plci[j-1];
8887 plci->State = LISTENING;
8888
8889 add_p(plci,OAD,"\x01\xfd");
8890
8891 add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8892
8893 add_p(plci,CAI,"\x01\xc0");
8894 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8895 add_p(plci,LLI,"\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8896 add_p(plci,SHIFT|6,NULL);
8897 add_p(plci,SIN,"\x02\x00\x00");
8898 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8899 sig_req(plci,ASSIGN,DSIG_ID);
8900 send_req(plci);
8901 }
8902 }
8903 }
8904}
8905
8906/*------------------------------------------------------------------*/
8907/* functions for all parameters sent in INDs */
8908/*------------------------------------------------------------------*/
8909
8910void IndParse(PLCI * plci, word * parms_id, byte ** parms, byte multiIEsize)
8911{
8912 word ploc; /* points to current location within packet */
8913 byte w;
8914 byte wlen;
8915 byte codeset,lock;
8916 byte * in;
8917 word i;
8918 word code;
8919 word mIEindex = 0;
8920 ploc = 0;
8921 codeset = 0;
8922 lock = 0;
8923
8924 in = plci->Sig.RBuffer->P;
8925 for(i=0; i<parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8926 { /* element but parms array is larger */
8927 parms[i] = (byte *)"";
8928 }
8929 for(i=0; i<multiIEsize; i++)
8930 {
8931 parms[i] = (byte *)"";
8932 }
8933
8934 while(ploc<plci->Sig.RBuffer->length-1) {
8935
8936 /* read information element id and length */
8937 w = in[ploc];
8938
8939 if(w & 0x80) {
8940/* w &=0xf0; removed, cannot detect congestion levels */
8941/* upper 4 bit masked with w==SHIFT now */
8942 wlen = 0;
8943 }
8944 else {
8945 wlen = (byte)(in[ploc+1]+1);
8946 }
8947 /* check if length valid (not exceeding end of packet) */
8948 if((ploc+wlen) > 270) return ;
8949 if(lock & 0x80) lock &=0x7f;
8950 else codeset = lock;
8951
8952 if((w&0xf0)==SHIFT) {
8953 codeset = in[ploc];
8954 if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8955 codeset &=7;
8956 lock |=0x80;
8957 }
8958 else {
8959 if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8960 else code = w;
8961 code |= (codeset<<8);
8962
8963 for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8964
8965 if(i<parms_id[0]+1) {
8966 if(!multiIEsize) { /* with multiIEs use next field index, */
8967 mIEindex = i-1; /* with normal IEs use same index like parms_id */
8968 }
8969
8970 parms[mIEindex] = &in[ploc+1];
8971 dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8972 if(parms_id[i]==OAD
8973 || parms_id[i]==CONN_NR
8974 || parms_id[i]==CAD) {
8975 if(in[ploc+2] &0x80) {
8976 in[ploc+0] = (byte)(in[ploc+1]+1);
8977 in[ploc+1] = (byte)(in[ploc+2] &0x7f);
8978 in[ploc+2] = 0x80;
8979 parms[mIEindex] = &in[ploc];
8980 }
8981 }
8982 mIEindex++; /* effects multiIEs only */
8983 }
8984 }
8985
8986 ploc +=(wlen+1);
8987 }
8988 return ;
8989}
8990
8991/*------------------------------------------------------------------*/
8992/* try to match a cip from received BC and HLC */
8993/*------------------------------------------------------------------*/
8994
8995byte ie_compare(byte * ie1, byte * ie2)
8996{
8997 word i;
8998 if(!ie1 || ! ie2) return FALSE;
8999 if(!ie1[0]) return FALSE;
9000 for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return FALSE;
9001 return TRUE;
9002}
9003
9004word find_cip(DIVA_CAPI_ADAPTER * a, byte * bc, byte * hlc)
9005{
9006 word i;
9007 word j;
9008
9009 for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9010
9011 for(j=16;j<29 &&
9012 (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9013 if(j==29) return i;
9014 return j;
9015}
9016
9017
9018static byte AddInfo(byte **add_i,
9019 byte **fty_i,
9020 byte *esc_chi,
9021 byte *facility)
9022{
9023 byte i;
9024 byte j;
9025 byte k;
9026 byte flen;
9027 byte len=0;
9028 /* facility is a nested structure */
9029 /* FTY can be more than once */
9030
9031 if(esc_chi[0] && !(esc_chi[esc_chi[0]])&0x7f )
9032 {
9033 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9034 }
9035
9036 else
9037 {
9038 add_i[0] = (byte *)"";
9039 }
9040 if(!fty_i[0][0])
9041 {
9042 add_i[3] = (byte *)"";
9043 }
9044 else
9045 { /* facility array found */
9046 for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9047 {
9048 dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9049 len += fty_i[i][0];
9050 len += 2;
9051 flen=fty_i[i][0];
9052 facility[j++]=0x1c; /* copy fac IE */
9053 for(k=0;k<=flen;k++,j++)
9054 {
9055 facility[j]=fty_i[i][k];
9056/* dbug(1,dprintf("%x ",facility[j])); */
9057 }
9058 }
9059 facility[0] = len;
9060 add_i[3] = facility;
9061 }
9062/* dbug(1,dprintf("FacArrLen=%d ",len)); */
9063 len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9064 len += 4; /* calculate length of all */
9065 return(len);
9066}
9067
9068/*------------------------------------------------------------------*/
9069/* voice and codec features */
9070/*------------------------------------------------------------------*/
9071
9072void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER * a)
9073{
9074 byte voice_chi[] = "\x02\x18\x01";
9075 byte channel;
9076
9077 channel = chi[chi[0]]&0x3;
9078 dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9079 voice_chi[2] = (channel) ? channel : 1;
9080 add_p(plci,FTY,"\x02\x01\x07"); /* B On, default on 1 */
9081 add_p(plci,ESC,voice_chi); /* Channel */
9082 sig_req(plci,TEL_CTRL,0);
9083 send_req(plci);
9084 if(a->AdvSignalPLCI)
9085 {
9086 adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9087 }
9088}
9089
9090void VoiceChannelOff(PLCI *plci)
9091{
9092 dbug(1,dprintf("ExtDevOFF"));
9093 add_p(plci,FTY,"\x02\x01\x08"); /* B Off */
9094 sig_req(plci,TEL_CTRL,0);
9095 send_req(plci);
9096 if(plci->adapter->AdvSignalPLCI)
9097 {
9098 adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9099 }
9100}
9101
9102
9103word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, byte hook_listen)
9104{
9105 word j;
9106 PLCI *splci;
9107
9108 /* check if hardware supports handset with hook states (adv.codec) */
9109 /* or if just a on board codec is supported */
9110 /* the advanced codec plci is just for internal use */
9111
9112 /* diva Pro with on-board codec: */
9113 if(a->profile.Global_Options & HANDSET)
9114 {
9115 /* new call, but hook states are already signalled */
9116 if(a->AdvCodecFLAG)
9117 {
9118 if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9119 {
9120 dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9121 return 0x2001; /* codec in use by another application */
9122 }
9123 if(plci!=0)
9124 {
9125 a->AdvSignalPLCI = plci;
9126 plci->tel=ADV_VOICE;
9127 }
9128 return 0; /* adv codec still used */
9129 }
9130 if((j=get_plci(a)))
9131 {
9132 splci = &a->plci[j-1];
9133 splci->tel = CODEC_PERMANENT;
9134 /* hook_listen indicates if a facility_req with handset/hook support */
9135 /* was sent. Otherwise if just a call on an external device was made */
9136 /* the codec will be used but the hook info will be discarded (just */
9137 /* the external controller is in use */
9138 if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9139 else
9140 {
9141 splci->State = ADVANCED_VOICE_NOSIG;
9142 if(plci)
9143 {
9144 plci->spoofed_msg = SPOOFING_REQUIRED;
9145 }
9146 /* indicate D-ch connect if */
9147 } /* codec is connected OK */
9148 if(plci!=0)
9149 {
9150 a->AdvSignalPLCI = plci;
9151 plci->tel=ADV_VOICE;
9152 }
9153 a->AdvSignalAppl = appl;
9154 a->AdvCodecFLAG = TRUE;
9155 a->AdvCodecPLCI = splci;
9156 add_p(splci,CAI,"\x01\x15");
9157 add_p(splci,LLI,"\x01\x00");
9158 add_p(splci,ESC,"\x02\x18\x00");
9159 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9160 splci->internal_command = PERM_COD_ASSIGN;
9161 dbug(1,dprintf("Codec Assign"));
9162 sig_req(splci,ASSIGN,DSIG_ID);
9163 send_req(splci);
9164 }
9165 else
9166 {
9167 return 0x2001; /* wrong state, no more plcis */
9168 }
9169 }
9170 else if(a->profile.Global_Options & ON_BOARD_CODEC)
9171 {
9172 if(hook_listen) return 0x300B; /* Facility not supported */
9173 /* no hook with SCOM */
9174 if(plci!=0) plci->tel = CODEC;
9175 dbug(1,dprintf("S/SCOM codec"));
9176 /* first time we use the scom-s codec we must shut down the internal */
9177 /* handset application of the card. This can be done by an assign with */
9178 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9179 if(!a->scom_appl_disable){
9180 if((j=get_plci(a))) {
9181 splci = &a->plci[j-1];
9182 add_p(splci,CAI,"\x01\x80");
9183 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9184 sig_req(splci,ASSIGN,0xC0); /* 0xc0 is the TEL_ID */
9185 send_req(splci);
9186 a->scom_appl_disable = TRUE;
9187 }
9188 else{
9189 return 0x2001; /* wrong state, no more plcis */
9190 }
9191 }
9192 }
9193 else return 0x300B; /* Facility not supported */
9194
9195 return 0;
9196}
9197
9198
9199void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9200{
9201
9202 dbug(1,dprintf("CodecIdCheck"));
9203
9204 if(a->AdvSignalPLCI == plci)
9205 {
9206 dbug(1,dprintf("PLCI owns codec"));
9207 VoiceChannelOff(a->AdvCodecPLCI);
9208 if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9209 {
9210 dbug(1,dprintf("remove temp codec PLCI"));
9211 plci_remove(a->AdvCodecPLCI);
9212 a->AdvCodecFLAG = 0;
9213 a->AdvCodecPLCI = NULL;
9214 a->AdvSignalAppl = NULL;
9215 }
9216 a->AdvSignalPLCI = NULL;
9217 }
9218}
9219
9220/* -------------------------------------------------------------------
9221 Ask for physical address of card on PCI bus
9222 ------------------------------------------------------------------- */
9223static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER * a,
9224 IDI_SYNC_REQ * preq) {
9225 a->sdram_bar = 0;
9226 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9227 ENTITY * e = (ENTITY *)preq;
9228
9229 e->user[0] = a->Id - 1;
9230 preq->xdi_sdram_bar.info.bar = 0;
9231 preq->xdi_sdram_bar.Req = 0;
9232 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9233
9234 (*(a->request))(e);
9235
9236 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9237 dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9238 }
9239}
9240
9241/* -------------------------------------------------------------------
9242 Ask XDI about extended features
9243 ------------------------------------------------------------------- */
9244static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a) {
9245 IDI_SYNC_REQ * preq;
9246 char buffer[ ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9247
9248 char features[4];
9249 preq = (IDI_SYNC_REQ *)&buffer[0];
9250
9251 if (!diva_xdi_extended_features) {
9252 ENTITY * e = (ENTITY *)preq;
9253 diva_xdi_extended_features |= 0x80000000;
9254
9255 e->user[0] = a->Id - 1;
9256 preq->xdi_extended_features.Req = 0;
9257 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9258 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9259 preq->xdi_extended_features.info.features = &features[0];
9260
9261 (*(a->request))(e);
9262
9263 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9264 /*
9265 Check features located in the byte '0'
9266 */
9267 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9268 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9269 }
9270 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9271 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9272 dbug(1,dprintf("XDI provides RxDMA"));
9273 }
9274 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9275 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9276 }
9277 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9278 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9279 dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9280 }
9281
9282 }
9283 }
9284
9285 diva_ask_for_xdi_sdram_bar (a, preq);
9286}
9287
9288/*------------------------------------------------------------------*/
9289/* automatic law */
9290/*------------------------------------------------------------------*/
9291/* called from OS specific part after init time to get the Law */
9292/* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9293void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9294{
9295 word j;
9296 PLCI *splci;
9297
9298 if(a->automatic_law) {
9299 return;
9300 }
9301 if((j=get_plci(a))) {
9302 diva_get_extended_adapter_features (a);
9303 splci = &a->plci[j-1];
9304 a->automatic_lawPLCI = splci;
9305 a->automatic_law = 1;
9306 add_p(splci,CAI,"\x01\x80");
9307 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9308 splci->internal_command = USELAW_REQ;
9309 splci->command = 0;
9310 splci->number = 0;
9311 sig_req(splci,ASSIGN,DSIG_ID);
9312 send_req(splci);
9313 }
9314}
9315
9316/* called from OS specific part if an application sends an Capi20Release */
9317word CapiRelease(word Id)
9318{
9319 word i, j, appls_found;
9320 PLCI *plci;
9321 APPL *this;
9322 DIVA_CAPI_ADAPTER *a;
9323
9324 if (!Id)
9325 {
9326 dbug(0,dprintf("A: CapiRelease(Id==0)"));
9327 return (_WRONG_APPL_ID);
9328 }
9329
9330 this = &application[Id-1]; /* get application pointer */
9331
9332 for(i=0,appls_found=0; i<max_appl; i++)
9333 {
9334 if(application[i].Id) /* an application has been found */
9335 {
9336 appls_found++;
9337 }
9338 }
9339
9340 for(i=0; i<max_adapter; i++) /* scan all adapters... */
9341 {
9342 a = &adapter[i];
9343 if (a->request)
9344 {
9345 a->Info_Mask[Id-1] = 0;
9346 a->CIP_Mask[Id-1] = 0;
9347 a->Notification_Mask[Id-1] = 0;
9348 a->codec_listen[Id-1] = NULL;
9349 a->requested_options_table[Id-1] = 0;
9350 for(j=0; j<a->max_plci; j++) /* and all PLCIs connected */
9351 { /* with this application */
9352 plci = &a->plci[j];
9353 if(plci->Id) /* if plci owns no application */
9354 { /* it may be not jet connected */
9355 if(plci->State==INC_CON_PENDING
9356 || plci->State==INC_CON_ALERT)
9357 {
9358 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9359 {
9360 clear_c_ind_mask_bit (plci, (word)(Id-1));
9361 if(c_ind_mask_empty (plci))
9362 {
9363 sig_req(plci,HANGUP,0);
9364 send_req(plci);
9365 plci->State = OUTG_DIS_PENDING;
9366 }
9367 }
9368 }
9369 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9370 {
9371 clear_c_ind_mask_bit (plci, (word)(Id-1));
9372 if(c_ind_mask_empty (plci))
9373 {
9374 if(!plci->appl)
9375 {
9376 plci_remove(plci);
9377 plci->State = IDLE;
9378 }
9379 }
9380 }
9381 if(plci->appl==this)
9382 {
9383 plci->appl = NULL;
9384 plci_remove(plci);
9385 plci->State = IDLE;
9386 }
9387 }
9388 }
9389 listen_check(a);
9390
9391 if(a->flag_dynamic_l1_down)
9392 {
9393 if(appls_found==1) /* last application does a capi release */
9394 {
9395 if((j=get_plci(a)))
9396 {
9397 plci = &a->plci[j-1];
9398 plci->command = 0;
9399 add_p(plci,OAD,"\x01\xfd");
9400 add_p(plci,CAI,"\x01\x80");
9401 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9402 add_p(plci,SHIFT|6,NULL);
9403 add_p(plci,SIN,"\x02\x00\x00");
9404 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9405 sig_req(plci,ASSIGN,DSIG_ID);
9406 add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9407 sig_req(plci,SIG_CTRL,0);
9408 send_req(plci);
9409 }
9410 }
9411 }
9412 if(a->AdvSignalAppl==this)
9413 {
9414 this->NullCREnable = FALSE;
9415 if (a->AdvCodecPLCI)
9416 {
9417 plci_remove(a->AdvCodecPLCI);
9418 a->AdvCodecPLCI->tel = 0;
9419 a->AdvCodecPLCI->adv_nl = 0;
9420 }
9421 a->AdvSignalAppl = NULL;
9422 a->AdvSignalPLCI = NULL;
9423 a->AdvCodecFLAG = 0;
9424 a->AdvCodecPLCI = NULL;
9425 }
9426 }
9427 }
9428
9429 this->Id = 0;
9430
9431 return GOOD;
9432}
9433
9434static word plci_remove_check(PLCI *plci)
9435{
9436 if(!plci) return TRUE;
9437 if(!plci->NL.Id && c_ind_mask_empty (plci))
9438 {
9439 if(plci->Sig.Id == 0xff)
9440 plci->Sig.Id = 0;
9441 if(!plci->Sig.Id)
9442 {
9443 dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9444 dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9445 if (plci->Id)
9446 {
9447 CodecIdCheck(plci->adapter, plci);
9448 clear_b1_config (plci);
9449 ncci_remove (plci, 0, FALSE);
9450 plci_free_msg_in_queue (plci);
9451 channel_flow_control_remove (plci);
9452 plci->Id = 0;
9453 plci->State = IDLE;
9454 plci->channels = 0;
9455 plci->appl = NULL;
9456 plci->notifiedcall = 0;
9457 }
9458 listen_check(plci->adapter);
9459 return TRUE;
9460 }
9461 }
9462 return FALSE;
9463}
9464
9465
9466/*------------------------------------------------------------------*/
9467
9468static byte plci_nl_busy (PLCI *plci)
9469{
9470 /* only applicable for non-multiplexed protocols */
9471 return (plci->nl_req
9472 || (plci->ncci_ring_list
9473 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9474 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9475}
9476
9477
9478/*------------------------------------------------------------------*/
9479/* DTMF facilities */
9480/*------------------------------------------------------------------*/
9481
9482
9483static struct
9484{
9485 byte send_mask;
9486 byte listen_mask;
9487 byte character;
9488 byte code;
9489} dtmf_digit_map[] =
9490{
9491 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9492 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9493 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9494 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9495 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9496 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9497 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9498 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9499 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9500 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9501 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9502 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9503 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9504 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9505 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9506 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9507 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9508 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9509 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9510 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9511
9512 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9513 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9514 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9515 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9516 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9517 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9518 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9519 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9520 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9521 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9522 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9523 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9524 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9525 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9526 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9527 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9528 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9529 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9530 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9531 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9532 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9533 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9534 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9535 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9536 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9537 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9538 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9539 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9540 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9541 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9542 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9543 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9544 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9545 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9546 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9547 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9548 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9549 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9550 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9551 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9552 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9553 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9554 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9555 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9556 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9557 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9558 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9559 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9560 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9561 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9562 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9563 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9564
9565};
9566
9567#define DTMF_DIGIT_MAP_ENTRIES (sizeof(dtmf_digit_map) / sizeof(dtmf_digit_map[0]))
9568
9569
9570static void dtmf_enable_receiver (PLCI *plci, byte enable_mask)
9571{
9572 word min_digit_duration, min_gap_duration;
9573
9574 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9575 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9576 (char *)(FILE_), __LINE__, enable_mask));
9577
9578 if (enable_mask != 0)
9579 {
9580 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9581 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9582 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9583 PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9584 PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9585 plci->NData[0].PLength = 5;
9586
9587 PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9588 plci->NData[0].PLength += 2;
9589 capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9590
9591 }
9592 else
9593 {
9594 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9595 plci->NData[0].PLength = 1;
9596
9597 capidtmf_recv_disable (&(plci->capidtmf_state));
9598
9599 }
9600 plci->NData[0].P = plci->internal_req_buffer;
9601 plci->NL.X = plci->NData;
9602 plci->NL.ReqCh = 0;
9603 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9604 plci->adapter->request (&plci->NL);
9605}
9606
9607
9608static void dtmf_send_digits (PLCI *plci, byte *digit_buffer, word digit_count)
9609{
9610 word w, i;
9611
9612 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9613 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9614 (char *)(FILE_), __LINE__, digit_count));
9615
9616 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9617 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9618 PUT_WORD (&plci->internal_req_buffer[1], w);
9619 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9620 PUT_WORD (&plci->internal_req_buffer[3], w);
9621 for (i = 0; i < digit_count; i++)
9622 {
9623 w = 0;
9624 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9625 && (digit_buffer[i] != dtmf_digit_map[w].character))
9626 {
9627 w++;
9628 }
9629 plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9630 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9631 }
9632 plci->NData[0].PLength = 5 + digit_count;
9633 plci->NData[0].P = plci->internal_req_buffer;
9634 plci->NL.X = plci->NData;
9635 plci->NL.ReqCh = 0;
9636 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9637 plci->adapter->request (&plci->NL);
9638}
9639
9640
9641static void dtmf_rec_clear_config (PLCI *plci)
9642{
9643
9644 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9645 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9646 (char *)(FILE_), __LINE__));
9647
9648 plci->dtmf_rec_active = 0;
9649 plci->dtmf_rec_pulse_ms = 0;
9650 plci->dtmf_rec_pause_ms = 0;
9651
9652 capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9653
9654}
9655
9656
9657static void dtmf_send_clear_config (PLCI *plci)
9658{
9659
9660 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9661 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9662 (char *)(FILE_), __LINE__));
9663
9664 plci->dtmf_send_requests = 0;
9665 plci->dtmf_send_pulse_ms = 0;
9666 plci->dtmf_send_pause_ms = 0;
9667}
9668
9669
9670static void dtmf_prepare_switch (dword Id, PLCI *plci)
9671{
9672
9673 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9674 UnMapId (Id), (char *)(FILE_), __LINE__));
9675
9676 while (plci->dtmf_send_requests != 0)
9677 dtmf_confirmation (Id, plci);
9678}
9679
9680
9681static word dtmf_save_config (dword Id, PLCI *plci, byte Rc)
9682{
9683
9684 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9685 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9686
9687 return (GOOD);
9688}
9689
9690
9691static word dtmf_restore_config (dword Id, PLCI *plci, byte Rc)
9692{
9693 word Info;
9694
9695 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9696 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9697
9698 Info = GOOD;
9699 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9700 {
9701 switch (plci->adjust_b_state)
9702 {
9703 case ADJUST_B_RESTORE_DTMF_1:
9704 plci->internal_command = plci->adjust_b_command;
9705 if (plci_nl_busy (plci))
9706 {
9707 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9708 break;
9709 }
9710 dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9711 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9712 break;
9713 case ADJUST_B_RESTORE_DTMF_2:
9714 if ((Rc != OK) && (Rc != OK_FC))
9715 {
9716 dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9717 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9718 Info = _WRONG_STATE;
9719 break;
9720 }
9721 break;
9722 }
9723 }
9724 return (Info);
9725}
9726
9727
9728static void dtmf_command (dword Id, PLCI *plci, byte Rc)
9729{
9730 word internal_command, Info;
9731 byte mask;
9732 byte result[4];
9733
9734 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9735 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9736 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9737 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9738
9739 Info = GOOD;
9740 result[0] = 2;
9741 PUT_WORD (&result[1], DTMF_SUCCESS);
9742 internal_command = plci->internal_command;
9743 plci->internal_command = 0;
9744 mask = 0x01;
9745 switch (plci->dtmf_cmd)
9746 {
9747
9748 case DTMF_LISTEN_TONE_START:
9749 mask <<= 1;
9750 case DTMF_LISTEN_MF_START:
9751 mask <<= 1;
9752
9753 case DTMF_LISTEN_START:
9754 switch (internal_command)
9755 {
9756 default:
9757 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9758 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9759 case DTMF_COMMAND_1:
9760 if (adjust_b_process (Id, plci, Rc) != GOOD)
9761 {
9762 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9763 UnMapId (Id), (char *)(FILE_), __LINE__));
9764 Info = _FACILITY_NOT_SUPPORTED;
9765 break;
9766 }
9767 if (plci->internal_command)
9768 return;
9769 case DTMF_COMMAND_2:
9770 if (plci_nl_busy (plci))
9771 {
9772 plci->internal_command = DTMF_COMMAND_2;
9773 return;
9774 }
9775 plci->internal_command = DTMF_COMMAND_3;
9776 dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9777 return;
9778 case DTMF_COMMAND_3:
9779 if ((Rc != OK) && (Rc != OK_FC))
9780 {
9781 dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9782 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9783 Info = _FACILITY_NOT_SUPPORTED;
9784 break;
9785 }
9786
9787 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9788
9789 plci->dtmf_rec_active |= mask;
9790 break;
9791 }
9792 break;
9793
9794
9795 case DTMF_LISTEN_TONE_STOP:
9796 mask <<= 1;
9797 case DTMF_LISTEN_MF_STOP:
9798 mask <<= 1;
9799
9800 case DTMF_LISTEN_STOP:
9801 switch (internal_command)
9802 {
9803 default:
9804 plci->dtmf_rec_active &= ~mask;
9805 if (plci->dtmf_rec_active)
9806 break;
9807/*
9808 case DTMF_COMMAND_1:
9809 if (plci->dtmf_rec_active)
9810 {
9811 if (plci_nl_busy (plci))
9812 {
9813 plci->internal_command = DTMF_COMMAND_1;
9814 return;
9815 }
9816 plci->dtmf_rec_active &= ~mask;
9817 plci->internal_command = DTMF_COMMAND_2;
9818 dtmf_enable_receiver (plci, FALSE);
9819 return;
9820 }
9821 Rc = OK;
9822 case DTMF_COMMAND_2:
9823 if ((Rc != OK) && (Rc != OK_FC))
9824 {
9825 dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9826 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9827 Info = _FACILITY_NOT_SUPPORTED;
9828 break;
9829 }
9830*/
9831 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9832 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9833 case DTMF_COMMAND_3:
9834 if (adjust_b_process (Id, plci, Rc) != GOOD)
9835 {
9836 dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9837 UnMapId (Id), (char *)(FILE_), __LINE__));
9838 Info = _FACILITY_NOT_SUPPORTED;
9839 break;
9840 }
9841 if (plci->internal_command)
9842 return;
9843 break;
9844 }
9845 break;
9846
9847
9848 case DTMF_SEND_TONE:
9849 mask <<= 1;
9850 case DTMF_SEND_MF:
9851 mask <<= 1;
9852
9853 case DTMF_DIGITS_SEND:
9854 switch (internal_command)
9855 {
9856 default:
9857 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9858 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9859 DTMF_COMMAND_1);
9860 case DTMF_COMMAND_1:
9861 if (adjust_b_process (Id, plci, Rc) != GOOD)
9862 {
9863 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9864 UnMapId (Id), (char *)(FILE_), __LINE__));
9865 Info = _FACILITY_NOT_SUPPORTED;
9866 break;
9867 }
9868 if (plci->internal_command)
9869 return;
9870 case DTMF_COMMAND_2:
9871 if (plci_nl_busy (plci))
9872 {
9873 plci->internal_command = DTMF_COMMAND_2;
9874 return;
9875 }
9876 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9877 plci->internal_command = DTMF_COMMAND_3;
9878 dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9879 return;
9880 case DTMF_COMMAND_3:
9881 if ((Rc != OK) && (Rc != OK_FC))
9882 {
9883 dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9884 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9885 if (plci->dtmf_send_requests != 0)
9886 (plci->dtmf_send_requests)--;
9887 Info = _FACILITY_NOT_SUPPORTED;
9888 break;
9889 }
9890 return;
9891 }
9892 break;
9893 }
9894 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9895 "wws", Info, SELECTOR_DTMF, result);
9896}
9897
9898
9899static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9900{
9901 word Info;
9902 word i, j;
9903 byte mask;
9904 API_PARSE dtmf_parms[5];
9905 byte result[40];
9906
9907 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9908 UnMapId (Id), (char *)(FILE_), __LINE__));
9909
9910 Info = GOOD;
9911 result[0] = 2;
9912 PUT_WORD (&result[1], DTMF_SUCCESS);
9913 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9914 {
9915 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9916 UnMapId (Id), (char *)(FILE_), __LINE__));
9917 Info = _FACILITY_NOT_SUPPORTED;
9918 }
9919 else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9920 {
9921 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9922 UnMapId (Id), (char *)(FILE_), __LINE__));
9923 Info = _WRONG_MESSAGE_FORMAT;
9924 }
9925
9926 else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9927 || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9928 {
9929 if (!((a->requested_options_table[appl->Id-1])
9930 & (1L << PRIVATE_DTMF_TONE)))
9931 {
9932 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9933 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9934 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9935 }
9936 else
9937 {
9938 for (i = 0; i < 32; i++)
9939 result[4 + i] = 0;
9940 if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9941 {
9942 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9943 {
9944 if (dtmf_digit_map[i].listen_mask != 0)
9945 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9946 }
9947 }
9948 else
9949 {
9950 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9951 {
9952 if (dtmf_digit_map[i].send_mask != 0)
9953 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9954 }
9955 }
9956 result[0] = 3 + 32;
9957 result[3] = 32;
9958 }
9959 }
9960
9961 else if (plci == NULL)
9962 {
9963 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9964 UnMapId (Id), (char *)(FILE_), __LINE__));
9965 Info = _WRONG_IDENTIFIER;
9966 }
9967 else
9968 {
9969 if (!plci->State
9970 || !plci->NL.Id || plci->nl_remove_id)
9971 {
9972 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9973 UnMapId (Id), (char *)(FILE_), __LINE__));
9974 Info = _WRONG_STATE;
9975 }
9976 else
9977 {
9978 plci->command = 0;
9979 plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
9980 mask = 0x01;
9981 switch (plci->dtmf_cmd)
9982 {
9983
9984 case DTMF_LISTEN_TONE_START:
9985 case DTMF_LISTEN_TONE_STOP:
9986 mask <<= 1;
9987 case DTMF_LISTEN_MF_START:
9988 case DTMF_LISTEN_MF_STOP:
9989 mask <<= 1;
9990 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
9991 & (1L << PRIVATE_DTMF_TONE)))
9992 {
9993 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9994 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9995 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9996 break;
9997 }
9998
9999 case DTMF_LISTEN_START:
10000 case DTMF_LISTEN_STOP:
10001 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10002 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10003 {
10004 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10005 UnMapId (Id), (char *)(FILE_), __LINE__));
10006 Info = _FACILITY_NOT_SUPPORTED;
10007 break;
10008 }
10009 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10010 {
10011 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10012 {
10013 plci->dtmf_rec_pulse_ms = 0;
10014 plci->dtmf_rec_pause_ms = 0;
10015 }
10016 else
10017 {
10018 plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10019 plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10020 }
10021 }
10022 start_internal_command (Id, plci, dtmf_command);
10023 return (FALSE);
10024
10025
10026 case DTMF_SEND_TONE:
10027 mask <<= 1;
10028 case DTMF_SEND_MF:
10029 mask <<= 1;
10030 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10031 & (1L << PRIVATE_DTMF_TONE)))
10032 {
10033 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10034 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10035 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10036 break;
10037 }
10038
10039 case DTMF_DIGITS_SEND:
10040 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10041 {
10042 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10043 UnMapId (Id), (char *)(FILE_), __LINE__));
10044 Info = _WRONG_MESSAGE_FORMAT;
10045 break;
10046 }
10047 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10048 {
10049 plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10050 plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10051 }
10052 i = 0;
10053 j = 0;
10054 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10055 {
10056 j = 0;
10057 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10058 && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10059 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10060 {
10061 j++;
10062 }
10063 i++;
10064 }
10065 if (j == DTMF_DIGIT_MAP_ENTRIES)
10066 {
10067 dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10068 UnMapId (Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10069 PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10070 break;
10071 }
10072 if (plci->dtmf_send_requests >=
10073 sizeof(plci->dtmf_msg_number_queue) / sizeof(plci->dtmf_msg_number_queue[0]))
10074 {
10075 dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10076 UnMapId (Id), (char *)(FILE_), __LINE__));
10077 Info = _WRONG_STATE;
10078 break;
10079 }
10080 api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10081 start_internal_command (Id, plci, dtmf_command);
10082 return (FALSE);
10083
10084 default:
10085 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10086 UnMapId (Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10087 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10088 }
10089 }
10090 }
10091 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10092 "wws", Info, SELECTOR_DTMF, result);
10093 return (FALSE);
10094}
10095
10096
10097static void dtmf_confirmation (dword Id, PLCI *plci)
10098{
10099 word Info;
10100 word i;
10101 byte result[4];
10102
10103 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10104 UnMapId (Id), (char *)(FILE_), __LINE__));
10105
10106 Info = GOOD;
10107 result[0] = 2;
10108 PUT_WORD (&result[1], DTMF_SUCCESS);
10109 if (plci->dtmf_send_requests != 0)
10110 {
10111 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10112 "wws", GOOD, SELECTOR_DTMF, result);
10113 (plci->dtmf_send_requests)--;
10114 for (i = 0; i < plci->dtmf_send_requests; i++)
10115 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];
10116 }
10117}
10118
10119
10120static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length)
10121{
10122 word i, j, n;
10123
10124 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10125 UnMapId (Id), (char *)(FILE_), __LINE__));
10126
10127 n = 0;
10128 for (i = 1; i < length; i++)
10129 {
10130 j = 0;
10131 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10132 && ((msg[i] != dtmf_digit_map[j].code)
10133 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10134 {
10135 j++;
10136 }
10137 if (j < DTMF_DIGIT_MAP_ENTRIES)
10138 {
10139
10140 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10141 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10142 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10143 {
10144 if (n + 1 == i)
10145 {
10146 for (i = length; i > n + 1; i--)
10147 msg[i] = msg[i - 1];
10148 length++;
10149 i++;
10150 }
10151 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10152 }
10153 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10154
10155 msg[++n] = dtmf_digit_map[j].character;
10156 }
10157 }
10158 if (n != 0)
10159 {
10160 msg[0] = (byte) n;
10161 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10162 }
10163}
10164
10165
10166/*------------------------------------------------------------------*/
10167/* DTMF parameters */
10168/*------------------------------------------------------------------*/
10169
10170static void dtmf_parameter_write (PLCI *plci)
10171{
10172 word i;
10173 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10174
10175 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10176 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10177 (char *)(FILE_), __LINE__));
10178
10179 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10180 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10181 for (i = 0; i < plci->dtmf_parameter_length; i++)
10182 parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10183 add_p (plci, FTY, parameter_buffer);
10184 sig_req (plci, TEL_CTRL, 0);
10185 send_req (plci);
10186}
10187
10188
10189static void dtmf_parameter_clear_config (PLCI *plci)
10190{
10191
10192 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10193 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10194 (char *)(FILE_), __LINE__));
10195
10196 plci->dtmf_parameter_length = 0;
10197}
10198
10199
10200static void dtmf_parameter_prepare_switch (dword Id, PLCI *plci)
10201{
10202
10203 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10204 UnMapId (Id), (char *)(FILE_), __LINE__));
10205
10206}
10207
10208
10209static word dtmf_parameter_save_config (dword Id, PLCI *plci, byte Rc)
10210{
10211
10212 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10213 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10214
10215 return (GOOD);
10216}
10217
10218
10219static word dtmf_parameter_restore_config (dword Id, PLCI *plci, byte Rc)
10220{
10221 word Info;
10222
10223 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10224 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10225
10226 Info = GOOD;
10227 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10228 && (plci->dtmf_parameter_length != 0))
10229 {
10230 switch (plci->adjust_b_state)
10231 {
10232 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10233 plci->internal_command = plci->adjust_b_command;
10234 if (plci->sig_req)
10235 {
10236 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10237 break;
10238 }
10239 dtmf_parameter_write (plci);
10240 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10241 break;
10242 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10243 if ((Rc != OK) && (Rc != OK_FC))
10244 {
10245 dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10246 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10247 Info = _WRONG_STATE;
10248 break;
10249 }
10250 break;
10251 }
10252 }
10253 return (Info);
10254}
10255
10256
10257/*------------------------------------------------------------------*/
10258/* Line interconnect facilities */
10259/*------------------------------------------------------------------*/
10260
10261
10262LI_CONFIG *li_config_table;
10263word li_total_channels;
10264
10265
10266/*------------------------------------------------------------------*/
10267/* translate a CHI information element to a channel number */
10268/* returns 0xff - any channel */
10269/* 0xfe - chi wrong coding */
10270/* 0xfd - D-channel */
10271/* 0x00 - no channel */
10272/* else channel number / PRI: timeslot */
10273/* if channels is provided we accept more than one channel. */
10274/*------------------------------------------------------------------*/
10275
10276static byte chi_to_channel (byte *chi, dword *pchannelmap)
10277{
10278 int p;
10279 int i;
10280 dword map;
10281 byte excl;
10282 byte ofs;
10283 byte ch;
10284
10285 if (pchannelmap) *pchannelmap = 0;
10286 if(!chi[0]) return 0xff;
10287 excl = 0;
10288
10289 if(chi[1] & 0x20) {
10290 if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10291 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10292 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10293 if((chi[1] |0xc8)!=0xe9) return 0xfe;
10294 if(chi[1] &0x08) excl = 0x40;
10295
10296 /* int. id present */
10297 if(chi[1] &0x40) {
10298 p=i+1;
10299 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10300 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10301 }
10302
10303 /* coding standard, Number/Map, Channel Type */
10304 p=i+1;
10305 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10306 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10307 if((chi[p]|0xd0)!=0xd3) return 0xfe;
10308
10309 /* Number/Map */
10310 if(chi[p] &0x10) {
10311
10312 /* map */
10313 if((chi[0]-p)==4) ofs = 0;
10314 else if((chi[0]-p)==3) ofs = 1;
10315 else return 0xfe;
10316 ch = 0;
10317 map = 0;
10318 for(i=0; i<4 && p<chi[0]; i++) {
10319 p++;
10320 ch += 8;
10321 map <<= 8;
10322 if(chi[p]) {
10323 for (ch=0; !(chi[p] & (1 << ch)); ch++);
10324 map |= chi[p];
10325 }
10326 }
10327 ch += ofs;
10328 map <<= ofs;
10329 }
10330 else {
10331
10332 /* number */
10333 p=i+1;
10334 ch = chi[p] &0x3f;
10335 if(pchannelmap) {
10336 if((byte)(chi[0]-p)>30) return 0xfe;
10337 map = 0;
10338 for(i=p; i<=chi[0]; i++) {
10339 if ((chi[i] &0x7f) > 31) return 0xfe;
10340 map |= (1L << (chi[i] &0x7f));
10341 }
10342 }
10343 else {
10344 if(p!=chi[0]) return 0xfe;
10345 if (ch > 31) return 0xfe;
10346 map = (1L << ch);
10347 }
10348 if(chi[p] &0x40) return 0xfe;
10349 }
10350 if (pchannelmap) *pchannelmap = map;
10351 else if (map != ((dword)(1L << ch))) return 0xfe;
10352 return (byte)(excl | ch);
10353 }
10354 else { /* not PRI */
10355 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10356 if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10357 if(chi[1] &0x08) excl = 0x40;
10358
10359 switch(chi[1] |0x98) {
10360 case 0x98: return 0;
10361 case 0x99:
10362 if (pchannelmap) *pchannelmap = 2;
10363 return excl |1;
10364 case 0x9a:
10365 if (pchannelmap) *pchannelmap = 4;
10366 return excl |2;
10367 case 0x9b: return 0xff;
10368 case 0x9c: return 0xfd; /* d-ch */
10369 default: return 0xfe;
10370 }
10371 }
10372}
10373
10374
10375static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id)
10376{
10377 DIVA_CAPI_ADAPTER *a;
10378 PLCI *splci;
10379 byte old_id;
10380
10381 a = plci->adapter;
10382 old_id = plci->li_bchannel_id;
10383 if (a->li_pri)
10384 {
10385 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10386 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10387 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10388 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10389 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10390 }
10391 else
10392 {
10393 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10394 {
10395 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10396 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10397 plci->li_bchannel_id = bchannel_id & 0x03;
10398 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10399 {
10400 splci = a->AdvSignalPLCI;
10401 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10402 {
10403 if ((splci->li_bchannel_id != 0)
10404 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10405 {
10406 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10407 }
10408 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10409 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10410 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10411 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10412 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10413 }
10414 }
10415 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10416 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10417 }
10418 }
10419 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10420 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10421 {
10422 mixer_clear_config (plci);
10423 }
10424 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10425 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10426 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10427}
10428
10429
10430static void mixer_set_bchannel_id (PLCI *plci, byte *chi)
10431{
10432 DIVA_CAPI_ADAPTER *a;
10433 PLCI *splci;
10434 byte ch, old_id;
10435
10436 a = plci->adapter;
10437 old_id = plci->li_bchannel_id;
10438 ch = chi_to_channel (chi, NULL);
10439 if (!(ch & 0x80))
10440 {
10441 if (a->li_pri)
10442 {
10443 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10444 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10445 plci->li_bchannel_id = (ch & 0x1f) + 1;
10446 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10447 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10448 }
10449 else
10450 {
10451 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10452 {
10453 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10454 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10455 plci->li_bchannel_id = ch & 0x1f;
10456 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10457 {
10458 splci = a->AdvSignalPLCI;
10459 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10460 {
10461 if ((splci->li_bchannel_id != 0)
10462 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10463 {
10464 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10465 }
10466 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10467 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10468 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10469 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10470 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10471 }
10472 }
10473 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10474 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10475 }
10476 }
10477 }
10478 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10479 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10480 {
10481 mixer_clear_config (plci);
10482 }
10483 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10484 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10485 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10486}
10487
10488
10489#define MIXER_MAX_DUMP_CHANNELS 34
10490
10491static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER *a)
10492{
10493static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10494 word n, i, j;
10495 char *p;
10496 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10497
10498 dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10499 (dword)(UnMapController (a->Id)), (char *)(FILE_), __LINE__));
10500
10501 for (i = 0; i < li_total_channels; i++)
10502 {
10503 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10504 if (li_config_table[i].chflags != 0)
10505 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10506 else
10507 {
10508 for (j = 0; j < li_total_channels; j++)
10509 {
10510 if (((li_config_table[i].flag_table[j]) != 0)
10511 || ((li_config_table[j].flag_table[i]) != 0))
10512 {
10513 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10514 }
10515 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10516 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10517 {
10518 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10519 }
10520 }
10521 }
10522 }
10523 for (i = 0; i < li_total_channels; i++)
10524 {
10525 for (j = 0; j < li_total_channels; j++)
10526 {
10527 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10528 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10529 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10530 }
10531 }
10532 for (n = 0; n < li_total_channels; n++)
10533 {
10534 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10535 {
10536 for (i = 0; i < li_total_channels; i++)
10537 {
10538 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10539 {
10540 for (j = 0; j < li_total_channels; j++)
10541 {
10542 li_config_table[i].coef_table[j] |=
10543 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10544 }
10545 }
10546 }
10547 }
10548 }
10549 for (i = 0; i < li_total_channels; i++)
10550 {
10551 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10552 {
10553 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10554 for (j = 0; j < li_total_channels; j++)
10555 {
10556 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10557 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10558 }
10559 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10560 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10561 }
10562 }
10563 for (i = 0; i < li_total_channels; i++)
10564 {
10565 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10566 {
10567 for (j = 0; j < li_total_channels; j++)
10568 {
10569 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10570 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10571 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10572 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10573 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10574 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10575 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10576 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10577 }
10578 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10579 {
10580 for (j = 0; j < li_total_channels; j++)
10581 {
10582 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10583 {
10584 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10585 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10586 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10587 }
10588 }
10589 }
10590 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10591 {
10592 for (j = 0; j < li_total_channels; j++)
10593 {
10594 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10595 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10596 }
10597 }
10598 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10599 {
10600 for (j = 0; j < li_total_channels; j++)
10601 {
10602 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10603 {
10604 for (n = 0; n < li_total_channels; n++)
10605 {
10606 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10607 {
10608 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10609 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10610 {
10611 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10612 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10613 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10614 }
10615 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10616 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10617 }
10618 }
10619 }
10620 }
10621 }
10622 }
10623 }
10624 for (i = 0; i < li_total_channels; i++)
10625 {
10626 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10627 {
10628 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10629 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10630 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10631 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10632 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10633 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10634 for (j = 0; j < li_total_channels; j++)
10635 {
10636 if ((li_config_table[i].flag_table[j] &
10637 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10638 || (li_config_table[j].flag_table[i] &
10639 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10640 {
10641 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10642 }
10643 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10644 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10645 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10646 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10647 }
10648 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10649 {
10650 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10651 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10652 }
10653 }
10654 }
10655 for (i = 0; i < li_total_channels; i++)
10656 {
10657 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10658 {
10659 j = 0;
10660 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10661 j++;
10662 if (j < li_total_channels)
10663 {
10664 for (j = 0; j < li_total_channels; j++)
10665 {
10666 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10667 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10668 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10669 }
10670 }
10671 }
10672 }
10673 n = li_total_channels;
10674 if (n > MIXER_MAX_DUMP_CHANNELS)
10675 n = MIXER_MAX_DUMP_CHANNELS;
10676 p = hex_line;
10677 for (j = 0; j < n; j++)
10678 {
10679 if ((j & 0x7) == 0)
10680 *(p++) = ' ';
10681 *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10682 *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10683 }
10684 *p = '\0';
10685 dbug (1, dprintf ("[%06lx] CURRENT %s",
10686 (dword)(UnMapController (a->Id)), (char *) hex_line));
10687 p = hex_line;
10688 for (j = 0; j < n; j++)
10689 {
10690 if ((j & 0x7) == 0)
10691 *(p++) = ' ';
10692 *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10693 *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10694 }
10695 *p = '\0';
10696 dbug (1, dprintf ("[%06lx] CHANNEL %s",
10697 (dword)(UnMapController (a->Id)), (char *) hex_line));
10698 p = hex_line;
10699 for (j = 0; j < n; j++)
10700 {
10701 if ((j & 0x7) == 0)
10702 *(p++) = ' ';
10703 *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10704 *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10705 }
10706 *p = '\0';
10707 dbug (1, dprintf ("[%06lx] CHFLAG %s",
10708 (dword)(UnMapController (a->Id)), (char *) hex_line));
10709 for (i = 0; i < n; i++)
10710 {
10711 p = hex_line;
10712 for (j = 0; j < n; j++)
10713 {
10714 if ((j & 0x7) == 0)
10715 *(p++) = ' ';
10716 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10717 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10718 }
10719 *p = '\0';
10720 dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10721 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10722 }
10723 for (i = 0; i < n; i++)
10724 {
10725 p = hex_line;
10726 for (j = 0; j < n; j++)
10727 {
10728 if ((j & 0x7) == 0)
10729 *(p++) = ' ';
10730 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10731 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10732 }
10733 *p = '\0';
10734 dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10735 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10736 }
10737}
10738
10739
10740static struct
10741{
10742 byte mask;
10743 byte line_flags;
10744} mixer_write_prog_pri[] =
10745{
10746 { LI_COEF_CH_CH, 0 },
10747 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10748 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10749 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10750};
10751
10752static struct
10753{
10754 byte from_ch;
10755 byte to_ch;
10756 byte mask;
10757 byte xconnect_override;
10758} mixer_write_prog_bri[] =
10759{
10760 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10761 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10762 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10763 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10764 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10765 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10766 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10767 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10768 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10769 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10770 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10771 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10772 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10773 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10774 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10775 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10776 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10777 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10778 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10779 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10780 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10781 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10782 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10783 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10784 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10785 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10786 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10787 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10788 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10789 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10790 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10791 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10792 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10793 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10794 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10795 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10796};
10797
10798static byte mixer_swapped_index_bri[] =
10799{
10800 18, /* B to B */
10801 19, /* Alt B to B */
10802 20, /* PC to B */
10803 21, /* Alt PC to B */
10804 22, /* IC to B */
10805 23, /* Alt IC to B */
10806 24, /* B to PC */
10807 25, /* Alt B to PC */
10808 26, /* PC to PC */
10809 27, /* Alt PC to PC */
10810 28, /* IC to PC */
10811 29, /* Alt IC to PC */
10812 30, /* B to IC */
10813 31, /* Alt B to IC */
10814 32, /* PC to IC */
10815 33, /* Alt PC to IC */
10816 34, /* IC to IC */
10817 35, /* Alt IC to IC */
10818 0, /* Alt B to Alt B */
10819 1, /* B to Alt B */
10820 2, /* Alt PC to Alt B */
10821 3, /* PC to Alt B */
10822 4, /* Alt IC to Alt B */
10823 5, /* IC to Alt B */
10824 6, /* Alt B to Alt PC */
10825 7, /* B to Alt PC */
10826 8, /* Alt PC to Alt PC */
10827 9, /* PC to Alt PC */
10828 10, /* Alt IC to Alt PC */
10829 11, /* IC to Alt PC */
10830 12, /* Alt B to Alt IC */
10831 13, /* B to Alt IC */
10832 14, /* Alt PC to Alt IC */
10833 15, /* PC to Alt IC */
10834 16, /* Alt IC to Alt IC */
10835 17 /* IC to Alt IC */
10836};
10837
10838static struct
10839{
10840 byte mask;
10841 byte from_pc;
10842 byte to_pc;
10843} xconnect_write_prog[] =
10844{
10845 { LI_COEF_CH_CH, FALSE, FALSE },
10846 { LI_COEF_CH_PC, FALSE, TRUE },
10847 { LI_COEF_PC_CH, TRUE, FALSE },
10848 { LI_COEF_PC_PC, TRUE, TRUE }
10849};
10850
10851
10852static void xconnect_query_addresses (PLCI *plci)
10853{
10854 DIVA_CAPI_ADAPTER *a;
10855 word w, ch;
10856 byte *p;
10857
10858 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10859 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10860 (char *)(FILE_), __LINE__));
10861
10862 a = plci->adapter;
10863 if (a->li_pri && ((plci->li_bchannel_id == 0)
10864 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10865 {
10866 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10867 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10868 (char *)(FILE_), __LINE__));
10869 return;
10870 }
10871 p = plci->internal_req_buffer;
10872 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10873 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10874 w = ch;
10875 *(p++) = (byte) w;
10876 *(p++) = (byte)(w >> 8);
10877 w = ch | XCONNECT_CHANNEL_PORT_PC;
10878 *(p++) = (byte) w;
10879 *(p++) = (byte)(w >> 8);
10880 plci->NData[0].P = plci->internal_req_buffer;
10881 plci->NData[0].PLength = p - plci->internal_req_buffer;
10882 plci->NL.X = plci->NData;
10883 plci->NL.ReqCh = 0;
10884 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10885 plci->adapter->request (&plci->NL);
10886}
10887
10888
10889static void xconnect_write_coefs (PLCI *plci, word internal_command)
10890{
10891
10892 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10893 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10894 (char *)(FILE_), __LINE__, internal_command));
10895
10896 plci->li_write_command = internal_command;
10897 plci->li_write_channel = 0;
10898}
10899
10900
10901static byte xconnect_write_coefs_process (dword Id, PLCI *plci, byte Rc)
10902{
10903 DIVA_CAPI_ADAPTER *a;
10904 word w, n, i, j, r, s, to_ch;
10905 dword d;
10906 byte *p;
10907 struct xconnect_transfer_address_s *transfer_address;
10908 byte ch_map[MIXER_CHANNELS_BRI];
10909
10910 dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10911 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10912
10913 a = plci->adapter;
10914 if ((plci->li_bchannel_id == 0)
10915 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10916 {
10917 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10918 UnMapId (Id), (char *)(FILE_), __LINE__));
10919 return (TRUE);
10920 }
10921 i = a->li_base + (plci->li_bchannel_id - 1);
10922 j = plci->li_write_channel;
10923 p = plci->internal_req_buffer;
10924 if (j != 0)
10925 {
10926 if ((Rc != OK) && (Rc != OK_FC))
10927 {
10928 dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10929 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10930 return (FALSE);
10931 }
10932 }
10933 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10934 {
10935 r = 0;
10936 s = 0;
10937 if (j < li_total_channels)
10938 {
10939 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10940 {
10941 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10942 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10943 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10944 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10945 }
10946 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10947 while ((j < li_total_channels)
10948 && ((r == 0)
10949 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10950 || (!li_config_table[j].adapter->li_pri
10951 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10952 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10953 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10954 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10955 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10956 || ((li_config_table[j].adapter->li_base != a->li_base)
10957 && !(r & s &
10958 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10959 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10960 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10961 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10962 {
10963 j++;
10964 if (j < li_total_channels)
10965 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10966 }
10967 }
10968 if (j < li_total_channels)
10969 {
10970 plci->internal_command = plci->li_write_command;
10971 if (plci_nl_busy (plci))
10972 return (TRUE);
10973 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10974 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10975 do
10976 {
10977 if (li_config_table[j].adapter->li_base != a->li_base)
10978 {
10979 r &= s &
10980 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10981 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10982 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10983 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10984 }
10985 n = 0;
10986 do
10987 {
10988 if (r & xconnect_write_prog[n].mask)
10989 {
10990 if (xconnect_write_prog[n].from_pc)
10991 transfer_address = &(li_config_table[j].send_pc);
10992 else
10993 transfer_address = &(li_config_table[j].send_b);
10994 d = transfer_address->card_address.low;
10995 *(p++) = (byte) d;
10996 *(p++) = (byte)(d >> 8);
10997 *(p++) = (byte)(d >> 16);
10998 *(p++) = (byte)(d >> 24);
10999 d = transfer_address->card_address.high;
11000 *(p++) = (byte) d;
11001 *(p++) = (byte)(d >> 8);
11002 *(p++) = (byte)(d >> 16);
11003 *(p++) = (byte)(d >> 24);
11004 d = transfer_address->offset;
11005 *(p++) = (byte) d;
11006 *(p++) = (byte)(d >> 8);
11007 *(p++) = (byte)(d >> 16);
11008 *(p++) = (byte)(d >> 24);
11009 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11010 *(p++) = (byte) w;
11011 *(p++) = (byte)(w >> 8);
11012 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11013 (li_config_table[i].adapter->u_law ?
11014 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11015 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11016 *(p++) = (byte) w;
11017 *(p++) = (byte) 0;
11018 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11019 }
11020 n++;
11021 } while ((n < sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0]))
11022 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11023 if (n == sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0]))
11024 {
11025 do
11026 {
11027 j++;
11028 if (j < li_total_channels)
11029 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11030 } while ((j < li_total_channels)
11031 && ((r == 0)
11032 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11033 || (!li_config_table[j].adapter->li_pri
11034 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11035 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11036 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11037 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11038 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11039 || ((li_config_table[j].adapter->li_base != a->li_base)
11040 && !(r & s &
11041 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11042 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11043 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11044 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11045 }
11046 } while ((j < li_total_channels)
11047 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11048 }
11049 else if (j == li_total_channels)
11050 {
11051 plci->internal_command = plci->li_write_command;
11052 if (plci_nl_busy (plci))
11053 return (TRUE);
11054 if (a->li_pri)
11055 {
11056 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11057 w = 0;
11058 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11059 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11060 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11061 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11062 *(p++) = (byte) w;
11063 *(p++) = (byte)(w >> 8);
11064 }
11065 else
11066 {
11067 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11068 w = 0;
11069 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11070 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11071 {
11072 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11073 }
11074 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11075 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11076 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11077 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11078 *(p++) = (byte) w;
11079 *(p++) = (byte)(w >> 8);
11080 for (j = 0; j < sizeof(ch_map); j += 2)
11081 {
11082 if (plci->li_bchannel_id == 2)
11083 {
11084 ch_map[j] = (byte)(j+1);
11085 ch_map[j+1] = (byte) j;
11086 }
11087 else
11088 {
11089 ch_map[j] = (byte) j;
11090 ch_map[j+1] = (byte)(j+1);
11091 }
11092 }
11093 for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
11094 {
11095 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11096 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11097 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11098 {
11099 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11100 mixer_write_prog_bri[n].xconnect_override :
11101 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11102 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11103 {
11104 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11105 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11106 }
11107 }
11108 else
11109 {
11110 *p = 0x00;
11111 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11112 {
11113 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11114 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11115 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11116 }
11117 }
11118 p++;
11119 }
11120 }
11121 j = li_total_channels + 1;
11122 }
11123 }
11124 else
11125 {
11126 if (j <= li_total_channels)
11127 {
11128 plci->internal_command = plci->li_write_command;
11129 if (plci_nl_busy (plci))
11130 return (TRUE);
11131 if (j < a->li_base)
11132 j = a->li_base;
11133 if (a->li_pri)
11134 {
11135 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11136 w = 0;
11137 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11138 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11139 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11140 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11141 *(p++) = (byte) w;
11142 *(p++) = (byte)(w >> 8);
11143 for (n = 0; n < sizeof(mixer_write_prog_pri) / sizeof(mixer_write_prog_pri[0]); n++)
11144 {
11145 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11146 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11147 {
11148 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11149 if (w & mixer_write_prog_pri[n].mask)
11150 {
11151 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11152 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11153 }
11154 else
11155 *(p++) = 0x00;
11156 }
11157 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11158 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11159 {
11160 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11161 if (w & mixer_write_prog_pri[n].mask)
11162 {
11163 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11164 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11165 }
11166 else
11167 *(p++) = 0x00;
11168 }
11169 }
11170 }
11171 else
11172 {
11173 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11174 w = 0;
11175 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11176 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11177 {
11178 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11179 }
11180 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11181 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11182 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11183 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11184 *(p++) = (byte) w;
11185 *(p++) = (byte)(w >> 8);
11186 for (j = 0; j < sizeof(ch_map); j += 2)
11187 {
11188 if (plci->li_bchannel_id == 2)
11189 {
11190 ch_map[j] = (byte)(j+1);
11191 ch_map[j+1] = (byte) j;
11192 }
11193 else
11194 {
11195 ch_map[j] = (byte) j;
11196 ch_map[j+1] = (byte)(j+1);
11197 }
11198 }
11199 for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
11200 {
11201 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11202 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11203 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11204 {
11205 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11206 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11207 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11208 }
11209 else
11210 {
11211 *p = 0x00;
11212 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11213 {
11214 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11215 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11216 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11217 }
11218 }
11219 p++;
11220 }
11221 }
11222 j = li_total_channels + 1;
11223 }
11224 }
11225 plci->li_write_channel = j;
11226 if (p != plci->internal_req_buffer)
11227 {
11228 plci->NData[0].P = plci->internal_req_buffer;
11229 plci->NData[0].PLength = p - plci->internal_req_buffer;
11230 plci->NL.X = plci->NData;
11231 plci->NL.ReqCh = 0;
11232 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11233 plci->adapter->request (&plci->NL);
11234 }
11235 return (TRUE);
11236}
11237
11238
11239static void mixer_notify_update (PLCI *plci, byte others)
11240{
11241 DIVA_CAPI_ADAPTER *a;
11242 word i, w;
11243 PLCI *notify_plci;
11244 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11245
11246 dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11247 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11248 (char *)(FILE_), __LINE__, others));
11249
11250 a = plci->adapter;
11251 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11252 {
11253 if (others)
11254 plci->li_notify_update = TRUE;
11255 i = 0;
11256 do
11257 {
11258 notify_plci = NULL;
11259 if (others)
11260 {
11261 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11262 i++;
11263 if (i < li_total_channels)
11264 notify_plci = li_config_table[i++].plci;
11265 }
11266 else
11267 {
11268 if ((plci->li_bchannel_id != 0)
11269 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11270 {
11271 notify_plci = plci;
11272 }
11273 }
11274 if ((notify_plci != NULL)
11275 && !notify_plci->li_notify_update
11276 && (notify_plci->appl != NULL)
11277 && (notify_plci->State)
11278 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11279 {
11280 notify_plci->li_notify_update = TRUE;
11281 ((CAPI_MSG *) msg)->header.length = 18;
11282 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11283 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11284 ((CAPI_MSG *) msg)->header.number = 0;
11285 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11286 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11287 ((CAPI_MSG *) msg)->header.ncci = 0;
11288 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11289 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11290 PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11291 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11292 w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11293 if (w != _QUEUE_FULL)
11294 {
11295 if (w != 0)
11296 {
11297 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11298 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11299 (char *)(FILE_), __LINE__,
11300 (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11301 }
11302 notify_plci->li_notify_update = FALSE;
11303 }
11304 }
11305 } while (others && (notify_plci != NULL));
11306 if (others)
11307 plci->li_notify_update = FALSE;
11308 }
11309}
11310
11311
11312static void mixer_clear_config (PLCI *plci)
11313{
11314 DIVA_CAPI_ADAPTER *a;
11315 word i, j;
11316
11317 dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11318 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11319 (char *)(FILE_), __LINE__));
11320
11321 plci->li_notify_update = FALSE;
11322 plci->li_plci_b_write_pos = 0;
11323 plci->li_plci_b_read_pos = 0;
11324 plci->li_plci_b_req_pos = 0;
11325 a = plci->adapter;
11326 if ((plci->li_bchannel_id != 0)
11327 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11328 {
11329 i = a->li_base + (plci->li_bchannel_id - 1);
11330 li_config_table[i].curchnl = 0;
11331 li_config_table[i].channel = 0;
11332 li_config_table[i].chflags = 0;
11333 for (j = 0; j < li_total_channels; j++)
11334 {
11335 li_config_table[j].flag_table[i] = 0;
11336 li_config_table[i].flag_table[j] = 0;
11337 li_config_table[i].coef_table[j] = 0;
11338 li_config_table[j].coef_table[i] = 0;
11339 }
11340 if (!a->li_pri)
11341 {
11342 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11343 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11344 {
11345 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11346 li_config_table[i].curchnl = 0;
11347 li_config_table[i].channel = 0;
11348 li_config_table[i].chflags = 0;
11349 for (j = 0; j < li_total_channels; j++)
11350 {
11351 li_config_table[i].flag_table[j] = 0;
11352 li_config_table[j].flag_table[i] = 0;
11353 li_config_table[i].coef_table[j] = 0;
11354 li_config_table[j].coef_table[i] = 0;
11355 }
11356 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11357 {
11358 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11359 li_config_table[i].curchnl = 0;
11360 li_config_table[i].channel = 0;
11361 li_config_table[i].chflags = 0;
11362 for (j = 0; j < li_total_channels; j++)
11363 {
11364 li_config_table[i].flag_table[j] = 0;
11365 li_config_table[j].flag_table[i] = 0;
11366 li_config_table[i].coef_table[j] = 0;
11367 li_config_table[j].coef_table[i] = 0;
11368 }
11369 }
11370 }
11371 }
11372 }
11373}
11374
11375
11376static void mixer_prepare_switch (dword Id, PLCI *plci)
11377{
11378
11379 dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11380 UnMapId (Id), (char *)(FILE_), __LINE__));
11381
11382 do
11383 {
11384 mixer_indication_coefs_set (Id, plci);
11385 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11386}
11387
11388
11389static word mixer_save_config (dword Id, PLCI *plci, byte Rc)
11390{
11391 DIVA_CAPI_ADAPTER *a;
11392 word i, j;
11393
11394 dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11395 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11396
11397 a = plci->adapter;
11398 if ((plci->li_bchannel_id != 0)
11399 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11400 {
11401 i = a->li_base + (plci->li_bchannel_id - 1);
11402 for (j = 0; j < li_total_channels; j++)
11403 {
11404 li_config_table[i].coef_table[j] &= 0xf;
11405 li_config_table[j].coef_table[i] &= 0xf;
11406 }
11407 if (!a->li_pri)
11408 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11409 }
11410 return (GOOD);
11411}
11412
11413
11414static word mixer_restore_config (dword Id, PLCI *plci, byte Rc)
11415{
11416 DIVA_CAPI_ADAPTER *a;
11417 word Info;
11418
11419 dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11420 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11421
11422 Info = GOOD;
11423 a = plci->adapter;
11424 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11425 && (plci->li_bchannel_id != 0)
11426 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11427 {
11428 switch (plci->adjust_b_state)
11429 {
11430 case ADJUST_B_RESTORE_MIXER_1:
11431 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11432 {
11433 plci->internal_command = plci->adjust_b_command;
11434 if (plci_nl_busy (plci))
11435 {
11436 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11437 break;
11438 }
11439 xconnect_query_addresses (plci);
11440 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11441 break;
11442 }
11443 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11444 Rc = OK;
11445 case ADJUST_B_RESTORE_MIXER_2:
11446 case ADJUST_B_RESTORE_MIXER_3:
11447 case ADJUST_B_RESTORE_MIXER_4:
11448 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11449 {
11450 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11451 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
11452 Info = _WRONG_STATE;
11453 break;
11454 }
11455 if (Rc == OK)
11456 {
11457 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11458 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11459 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11460 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11461 }
11462 else if (Rc == 0)
11463 {
11464 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11465 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11466 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11467 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11468 }
11469 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11470 {
11471 plci->internal_command = plci->adjust_b_command;
11472 break;
11473 }
11474 case ADJUST_B_RESTORE_MIXER_5:
11475 xconnect_write_coefs (plci, plci->adjust_b_command);
11476 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11477 Rc = OK;
11478 case ADJUST_B_RESTORE_MIXER_6:
11479 if (!xconnect_write_coefs_process (Id, plci, Rc))
11480 {
11481 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11482 UnMapId (Id), (char *)(FILE_), __LINE__));
11483 Info = _FACILITY_NOT_SUPPORTED;
11484 break;
11485 }
11486 if (plci->internal_command)
11487 break;
11488 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11489 case ADJUST_B_RESTORE_MIXER_7:
11490 break;
11491 }
11492 }
11493 return (Info);
11494}
11495
11496
11497static void mixer_command (dword Id, PLCI *plci, byte Rc)
11498{
11499 DIVA_CAPI_ADAPTER *a;
11500 word i, internal_command, Info;
11501
11502 dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11503 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11504 plci->li_cmd));
11505
11506 Info = GOOD;
11507 a = plci->adapter;
11508 internal_command = plci->internal_command;
11509 plci->internal_command = 0;
11510 switch (plci->li_cmd)
11511 {
11512 case LI_REQ_CONNECT:
11513 case LI_REQ_DISCONNECT:
11514 case LI_REQ_SILENT_UPDATE:
11515 switch (internal_command)
11516 {
11517 default:
11518 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11519 {
11520 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11521 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11522 }
11523 case MIXER_COMMAND_1:
11524 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11525 {
11526 if (adjust_b_process (Id, plci, Rc) != GOOD)
11527 {
11528 dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11529 UnMapId (Id), (char *)(FILE_), __LINE__));
11530 Info = _FACILITY_NOT_SUPPORTED;
11531 break;
11532 }
11533 if (plci->internal_command)
11534 return;
11535 }
11536 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11537 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11538 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11539 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11540 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11541 {
11542 xconnect_write_coefs (plci, MIXER_COMMAND_2);
11543 }
11544 else
11545 {
11546 do
11547 {
11548 mixer_indication_coefs_set (Id, plci);
11549 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11550 }
11551 case MIXER_COMMAND_2:
11552 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11553 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11554 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11555 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11556 {
11557 if (!xconnect_write_coefs_process (Id, plci, Rc))
11558 {
11559 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11560 UnMapId (Id), (char *)(FILE_), __LINE__));
11561 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11562 {
11563 do
11564 {
11565 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11566 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11567 i = (plci->li_plci_b_write_pos == 0) ?
11568 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11569 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11570 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11571 }
11572 Info = _FACILITY_NOT_SUPPORTED;
11573 break;
11574 }
11575 if (plci->internal_command)
11576 return;
11577 }
11578 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11579 {
11580 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11581 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11582 }
11583 case MIXER_COMMAND_3:
11584 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11585 {
11586 if (adjust_b_process (Id, plci, Rc) != GOOD)
11587 {
11588 dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11589 UnMapId (Id), (char *)(FILE_), __LINE__));
11590 Info = _FACILITY_NOT_SUPPORTED;
11591 break;
11592 }
11593 if (plci->internal_command)
11594 return;
11595 }
11596 break;
11597 }
11598 break;
11599 }
11600 if ((plci->li_bchannel_id == 0)
11601 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11602 {
11603 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11604 UnMapId (Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11605 }
11606 else
11607 {
11608 i = a->li_base + (plci->li_bchannel_id - 1);
11609 li_config_table[i].curchnl = plci->li_channel_bits;
11610 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11611 {
11612 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11613 li_config_table[i].curchnl = plci->li_channel_bits;
11614 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11615 {
11616 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11617 li_config_table[i].curchnl = plci->li_channel_bits;
11618 }
11619 }
11620 }
11621}
11622
11623
11624static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11625 dword plci_b_id, byte connect, dword li_flags)
11626{
11627 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11628 PLCI *plci_b;
11629 DIVA_CAPI_ADAPTER *a_b;
11630
11631 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11632 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11633 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11634 if (!a->li_pri && (plci->tel == ADV_VOICE)
11635 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11636 {
11637 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11638 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11639 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11640 }
11641 else
11642 {
11643 ch_a_v = ch_a;
11644 ch_a_s = ch_a;
11645 }
11646 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11647 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11648 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11649 {
11650 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11651 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11652 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11653 }
11654 else
11655 {
11656 ch_b_v = ch_b;
11657 ch_b_s = ch_b;
11658 }
11659 if (connect)
11660 {
11661 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11662 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11663 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11664 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11665 }
11666 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11667 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11668 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11669 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11670 if (ch_a_v == ch_b_v)
11671 {
11672 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11673 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11674 }
11675 else
11676 {
11677 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11678 {
11679 for (i = 0; i < li_total_channels; i++)
11680 {
11681 if (i != ch_a_v)
11682 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11683 }
11684 }
11685 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11686 {
11687 for (i = 0; i < li_total_channels; i++)
11688 {
11689 if (i != ch_a_s)
11690 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11691 }
11692 }
11693 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11694 {
11695 for (i = 0; i < li_total_channels; i++)
11696 {
11697 if (i != ch_a_v)
11698 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11699 }
11700 }
11701 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11702 {
11703 for (i = 0; i < li_total_channels; i++)
11704 {
11705 if (i != ch_a_s)
11706 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11707 }
11708 }
11709 }
11710 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11711 {
11712 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11713 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11714 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11715 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11716 }
11717 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11718 {
11719 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11720 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11721 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11722 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11723 }
11724 if (li_flags & LI_FLAG_MONITOR_A)
11725 {
11726 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11727 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11728 }
11729 if (li_flags & LI_FLAG_MONITOR_B)
11730 {
11731 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11732 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11733 }
11734 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11735 {
11736 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11737 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11738 }
11739 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11740 {
11741 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11742 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11743 }
11744 if (li_flags & LI_FLAG_MIX_A)
11745 {
11746 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11747 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11748 }
11749 if (li_flags & LI_FLAG_MIX_B)
11750 {
11751 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11752 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11753 }
11754 if (ch_a_v != ch_a_s)
11755 {
11756 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11757 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11758 }
11759 if (ch_b_v != ch_b_s)
11760 {
11761 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11762 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11763 }
11764}
11765
11766
11767static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11768 dword plci_b_id, byte connect, dword li_flags)
11769{
11770 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11771 PLCI *plci_b;
11772 DIVA_CAPI_ADAPTER *a_b;
11773
11774 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11775 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11776 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11777 if (!a->li_pri && (plci->tel == ADV_VOICE)
11778 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11779 {
11780 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11781 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11782 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11783 }
11784 else
11785 {
11786 ch_a_v = ch_a;
11787 ch_a_s = ch_a;
11788 }
11789 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11790 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11791 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11792 {
11793 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11794 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11795 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11796 }
11797 else
11798 {
11799 ch_b_v = ch_b;
11800 ch_b_s = ch_b;
11801 }
11802 if (connect)
11803 {
11804 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11805 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11806 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11807 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11808 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11809 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11810 }
11811 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11812 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11813 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11814 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11815 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11816 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11817 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11818 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11819 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11820 {
11821 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11822 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11823 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11824 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11825 }
11826 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11827 {
11828 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11829 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11830 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11831 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11832 }
11833 if (li_flags & LI2_FLAG_MONITOR_B)
11834 {
11835 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11836 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11837 }
11838 if (li_flags & LI2_FLAG_MIX_B)
11839 {
11840 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11841 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11842 }
11843 if (li_flags & LI2_FLAG_MONITOR_X)
11844 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11845 if (li_flags & LI2_FLAG_MIX_X)
11846 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11847 if (li_flags & LI2_FLAG_LOOP_B)
11848 {
11849 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11850 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11851 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11852 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11853 }
11854 if (li_flags & LI2_FLAG_LOOP_PC)
11855 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11856 if (li_flags & LI2_FLAG_LOOP_X)
11857 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11858 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11859 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11860 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11861 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11862 if (ch_a_v != ch_a_s)
11863 {
11864 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11865 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11866 }
11867 if (ch_b_v != ch_b_s)
11868 {
11869 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11870 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11871 }
11872}
11873
11874
11875static word li_check_main_plci (dword Id, PLCI *plci)
11876{
11877 if (plci == NULL)
11878 {
11879 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11880 UnMapId (Id), (char *)(FILE_), __LINE__));
11881 return (_WRONG_IDENTIFIER);
11882 }
11883 if (!plci->State
11884 || !plci->NL.Id || plci->nl_remove_id
11885 || (plci->li_bchannel_id == 0))
11886 {
11887 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11888 UnMapId (Id), (char *)(FILE_), __LINE__));
11889 return (_WRONG_STATE);
11890 }
11891 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11892 return (GOOD);
11893}
11894
11895
11896static PLCI *li_check_plci_b (dword Id, PLCI *plci,
11897 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11898{
11899 byte ctlr_b;
11900 PLCI *plci_b;
11901
11902 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11903 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11904 {
11905 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11906 UnMapId (Id), (char *)(FILE_), __LINE__));
11907 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11908 return (NULL);
11909 }
11910 ctlr_b = 0;
11911 if ((plci_b_id & 0x7f) != 0)
11912 {
11913 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11914 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11915 ctlr_b = 0;
11916 }
11917 if ((ctlr_b == 0)
11918 || (((plci_b_id >> 8) & 0xff) == 0)
11919 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11920 {
11921 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11922 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11923 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11924 return (NULL);
11925 }
11926 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11927 if (!plci_b->State
11928 || !plci_b->NL.Id || plci_b->nl_remove_id
11929 || (plci_b->li_bchannel_id == 0))
11930 {
11931 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11932 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11933 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11934 return (NULL);
11935 }
11936 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11937 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11938 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11939 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11940 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11941 {
11942 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11943 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11944 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11945 return (NULL);
11946 }
11947 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11948 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11949 {
11950 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11951 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11952 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11953 return (NULL);
11954 }
11955 return (plci_b);
11956}
11957
11958
11959static PLCI *li2_check_plci_b (dword Id, PLCI *plci,
11960 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11961{
11962 byte ctlr_b;
11963 PLCI *plci_b;
11964
11965 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11966 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11967 {
11968 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11969 UnMapId (Id), (char *)(FILE_), __LINE__));
11970 PUT_WORD (p_result, _WRONG_STATE);
11971 return (NULL);
11972 }
11973 ctlr_b = 0;
11974 if ((plci_b_id & 0x7f) != 0)
11975 {
11976 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11977 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11978 ctlr_b = 0;
11979 }
11980 if ((ctlr_b == 0)
11981 || (((plci_b_id >> 8) & 0xff) == 0)
11982 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11983 {
11984 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11985 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11986 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11987 return (NULL);
11988 }
11989 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11990 if (!plci_b->State
11991 || !plci_b->NL.Id || plci_b->nl_remove_id
11992 || (plci_b->li_bchannel_id == 0)
11993 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11994 {
11995 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11996 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11997 PUT_WORD (p_result, _WRONG_STATE);
11998 return (NULL);
11999 }
12000 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12001 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12002 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12003 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12004 {
12005 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12006 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12007 PUT_WORD (p_result, _WRONG_IDENTIFIER);
12008 return (NULL);
12009 }
12010 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12011 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12012 {
12013 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12014 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12015 PUT_WORD (p_result, _WRONG_STATE);
12016 return (NULL);
12017 }
12018 return (plci_b);
12019}
12020
12021
12022static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12023{
12024 word Info;
12025 word i;
12026 dword d, li_flags, plci_b_id;
12027 PLCI *plci_b;
12028 API_PARSE li_parms[3];
12029 API_PARSE li_req_parms[3];
12030 API_PARSE li_participant_struct[2];
12031 API_PARSE li_participant_parms[3];
12032 word participant_parms_pos;
12033 byte result_buffer[32];
12034 byte *result;
12035 word result_pos;
12036 word plci_b_write_pos;
12037
12038 dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12039 UnMapId (Id), (char *)(FILE_), __LINE__));
12040
12041 Info = GOOD;
12042 result = result_buffer;
12043 result_buffer[0] = 0;
12044 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12045 {
12046 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12047 UnMapId (Id), (char *)(FILE_), __LINE__));
12048 Info = _FACILITY_NOT_SUPPORTED;
12049 }
12050 else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12051 {
12052 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12053 UnMapId (Id), (char *)(FILE_), __LINE__));
12054 Info = _WRONG_MESSAGE_FORMAT;
12055 }
12056 else
12057 {
12058 result_buffer[0] = 3;
12059 PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12060 result_buffer[3] = 0;
12061 switch (GET_WORD (li_parms[0].info))
12062 {
12063 case LI_GET_SUPPORTED_SERVICES:
12064 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12065 {
12066 result_buffer[0] = 17;
12067 result_buffer[3] = 14;
12068 PUT_WORD (&result_buffer[4], GOOD);
12069 d = 0;
12070 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12071 d |= LI_CONFERENCING_SUPPORTED;
12072 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12073 d |= LI_MONITORING_SUPPORTED;
12074 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12075 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12076 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12077 d |= LI_CROSS_CONTROLLER_SUPPORTED;
12078 PUT_DWORD (&result_buffer[6], d);
12079 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12080 {
12081 d = 0;
12082 for (i = 0; i < li_total_channels; i++)
12083 {
12084 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12085 && (li_config_table[i].adapter->li_pri
12086 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12087 {
12088 d++;
12089 }
12090 }
12091 }
12092 else
12093 {
12094 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12095 }
12096 PUT_DWORD (&result_buffer[10], d / 2);
12097 PUT_DWORD (&result_buffer[14], d);
12098 }
12099 else
12100 {
12101 result_buffer[0] = 25;
12102 result_buffer[3] = 22;
12103 PUT_WORD (&result_buffer[4], GOOD);
12104 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12105 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12106 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12107 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12108 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12109 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12110 d |= LI2_PC_LOOPING_SUPPORTED;
12111 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12112 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12113 PUT_DWORD (&result_buffer[6], d);
12114 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12115 PUT_DWORD (&result_buffer[10], d / 2);
12116 PUT_DWORD (&result_buffer[14], d - 1);
12117 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12118 {
12119 d = 0;
12120 for (i = 0; i < li_total_channels; i++)
12121 {
12122 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12123 && (li_config_table[i].adapter->li_pri
12124 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12125 {
12126 d++;
12127 }
12128 }
12129 }
12130 PUT_DWORD (&result_buffer[18], d / 2);
12131 PUT_DWORD (&result_buffer[22], d - 1);
12132 }
12133 break;
12134
12135 case LI_REQ_CONNECT:
12136 if (li_parms[1].length == 8)
12137 {
12138 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12139 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12140 {
12141 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12142 UnMapId (Id), (char *)(FILE_), __LINE__));
12143 Info = _WRONG_MESSAGE_FORMAT;
12144 break;
12145 }
12146 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12147 li_flags = GET_DWORD (li_req_parms[1].info);
12148 Info = li_check_main_plci (Id, plci);
12149 result_buffer[0] = 9;
12150 result_buffer[3] = 6;
12151 PUT_DWORD (&result_buffer[4], plci_b_id);
12152 PUT_WORD (&result_buffer[8], GOOD);
12153 if (Info != GOOD)
12154 break;
12155 result = plci->saved_msg.info;
12156 for (i = 0; i <= result_buffer[0]; i++)
12157 result[i] = result_buffer[i];
12158 plci_b_write_pos = plci->li_plci_b_write_pos;
12159 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12160 if (plci_b == NULL)
12161 break;
12162 li_update_connect (Id, a, plci, plci_b_id, TRUE, li_flags);
12163 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12164 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12165 plci->li_plci_b_write_pos = plci_b_write_pos;
12166 }
12167 else
12168 {
12169 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12170 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12171 {
12172 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12173 UnMapId (Id), (char *)(FILE_), __LINE__));
12174 Info = _WRONG_MESSAGE_FORMAT;
12175 break;
12176 }
12177 li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12178 Info = li_check_main_plci (Id, plci);
12179 result_buffer[0] = 7;
12180 result_buffer[3] = 4;
12181 PUT_WORD (&result_buffer[4], Info);
12182 result_buffer[6] = 0;
12183 if (Info != GOOD)
12184 break;
12185 result = plci->saved_msg.info;
12186 for (i = 0; i <= result_buffer[0]; i++)
12187 result[i] = result_buffer[i];
12188 plci_b_write_pos = plci->li_plci_b_write_pos;
12189 participant_parms_pos = 0;
12190 result_pos = 7;
12191 li2_update_connect (Id, a, plci, UnMapId (Id), TRUE, li_flags);
12192 while (participant_parms_pos < li_req_parms[1].length)
12193 {
12194 result[result_pos] = 6;
12195 result_pos += 7;
12196 PUT_DWORD (&result[result_pos - 6], 0);
12197 PUT_WORD (&result[result_pos - 2], GOOD);
12198 if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12199 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12200 {
12201 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12202 UnMapId (Id), (char *)(FILE_), __LINE__));
12203 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12204 break;
12205 }
12206 if (api_parse (&li_participant_struct[0].info[1],
12207 li_participant_struct[0].length, "dd", li_participant_parms))
12208 {
12209 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12210 UnMapId (Id), (char *)(FILE_), __LINE__));
12211 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12212 break;
12213 }
12214 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12215 li_flags = GET_DWORD (li_participant_parms[1].info);
12216 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12217 if (sizeof(result) - result_pos < 7)
12218 {
12219 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12220 UnMapId (Id), (char *)(FILE_), __LINE__));
12221 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12222 break;
12223 }
12224 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12225 if (plci_b != NULL)
12226 {
12227 li2_update_connect (Id, a, plci, plci_b_id, TRUE, li_flags);
12228 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12229 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12230 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12231 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12232 }
12233 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12234 (&li_req_parms[1].info[1]));
12235 }
12236 result[0] = (byte)(result_pos - 1);
12237 result[3] = (byte)(result_pos - 4);
12238 result[6] = (byte)(result_pos - 7);
12239 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12240 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12241 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12242 {
12243 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12244 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12245 }
12246 else
12247 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12248 plci->li_plci_b_write_pos = plci_b_write_pos;
12249 }
12250 mixer_calculate_coefs (a);
12251 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12252 mixer_notify_update (plci, TRUE);
12253 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12254 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12255 plci->command = 0;
12256 plci->li_cmd = GET_WORD (li_parms[0].info);
12257 start_internal_command (Id, plci, mixer_command);
12258 return (FALSE);
12259
12260 case LI_REQ_DISCONNECT:
12261 if (li_parms[1].length == 4)
12262 {
12263 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12264 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12265 {
12266 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12267 UnMapId (Id), (char *)(FILE_), __LINE__));
12268 Info = _WRONG_MESSAGE_FORMAT;
12269 break;
12270 }
12271 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12272 Info = li_check_main_plci (Id, plci);
12273 result_buffer[0] = 9;
12274 result_buffer[3] = 6;
12275 PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12276 PUT_WORD (&result_buffer[8], GOOD);
12277 if (Info != GOOD)
12278 break;
12279 result = plci->saved_msg.info;
12280 for (i = 0; i <= result_buffer[0]; i++)
12281 result[i] = result_buffer[i];
12282 plci_b_write_pos = plci->li_plci_b_write_pos;
12283 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12284 if (plci_b == NULL)
12285 break;
12286 li_update_connect (Id, a, plci, plci_b_id, FALSE, 0);
12287 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12288 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12289 plci->li_plci_b_write_pos = plci_b_write_pos;
12290 }
12291 else
12292 {
12293 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12294 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12295 {
12296 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12297 UnMapId (Id), (char *)(FILE_), __LINE__));
12298 Info = _WRONG_MESSAGE_FORMAT;
12299 break;
12300 }
12301 Info = li_check_main_plci (Id, plci);
12302 result_buffer[0] = 7;
12303 result_buffer[3] = 4;
12304 PUT_WORD (&result_buffer[4], Info);
12305 result_buffer[6] = 0;
12306 if (Info != GOOD)
12307 break;
12308 result = plci->saved_msg.info;
12309 for (i = 0; i <= result_buffer[0]; i++)
12310 result[i] = result_buffer[i];
12311 plci_b_write_pos = plci->li_plci_b_write_pos;
12312 participant_parms_pos = 0;
12313 result_pos = 7;
12314 while (participant_parms_pos < li_req_parms[0].length)
12315 {
12316 result[result_pos] = 6;
12317 result_pos += 7;
12318 PUT_DWORD (&result[result_pos - 6], 0);
12319 PUT_WORD (&result[result_pos - 2], GOOD);
12320 if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12321 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12322 {
12323 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12324 UnMapId (Id), (char *)(FILE_), __LINE__));
12325 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12326 break;
12327 }
12328 if (api_parse (&li_participant_struct[0].info[1],
12329 li_participant_struct[0].length, "d", li_participant_parms))
12330 {
12331 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12332 UnMapId (Id), (char *)(FILE_), __LINE__));
12333 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12334 break;
12335 }
12336 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12337 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12338 if (sizeof(result) - result_pos < 7)
12339 {
12340 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12341 UnMapId (Id), (char *)(FILE_), __LINE__));
12342 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12343 break;
12344 }
12345 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12346 if (plci_b != NULL)
12347 {
12348 li2_update_connect (Id, a, plci, plci_b_id, FALSE, 0);
12349 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12350 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12351 }
12352 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12353 (&li_req_parms[0].info[1]));
12354 }
12355 result[0] = (byte)(result_pos - 1);
12356 result[3] = (byte)(result_pos - 4);
12357 result[6] = (byte)(result_pos - 7);
12358 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12359 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12360 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12361 {
12362 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12363 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12364 }
12365 else
12366 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12367 plci->li_plci_b_write_pos = plci_b_write_pos;
12368 }
12369 mixer_calculate_coefs (a);
12370 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12371 mixer_notify_update (plci, TRUE);
12372 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12373 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12374 plci->command = 0;
12375 plci->li_cmd = GET_WORD (li_parms[0].info);
12376 start_internal_command (Id, plci, mixer_command);
12377 return (FALSE);
12378
12379 case LI_REQ_SILENT_UPDATE:
12380 if (!plci || !plci->State
12381 || !plci->NL.Id || plci->nl_remove_id
12382 || (plci->li_bchannel_id == 0)
12383 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12384 {
12385 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12386 UnMapId (Id), (char *)(FILE_), __LINE__));
12387 return (FALSE);
12388 }
12389 plci_b_write_pos = plci->li_plci_b_write_pos;
12390 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12391 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12392 {
12393 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12394 UnMapId (Id), (char *)(FILE_), __LINE__));
12395 return (FALSE);
12396 }
12397 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12398 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12399 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12400 {
12401 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12402 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12403 }
12404 else
12405 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12406 plci->li_plci_b_write_pos = plci_b_write_pos;
12407 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12408 plci->command = 0;
12409 plci->li_cmd = GET_WORD (li_parms[0].info);
12410 start_internal_command (Id, plci, mixer_command);
12411 return (FALSE);
12412
12413 default:
12414 dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12415 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12416 Info = _FACILITY_NOT_SUPPORTED;
12417 }
12418 }
12419 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12420 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12421 return (FALSE);
12422}
12423
12424
12425static void mixer_indication_coefs_set (dword Id, PLCI *plci)
12426{
12427 dword d;
12428 DIVA_CAPI_ADAPTER *a;
12429 byte result[12];
12430
12431 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12432 UnMapId (Id), (char *)(FILE_), __LINE__));
12433
12434 a = plci->adapter;
12435 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12436 {
12437 do
12438 {
12439 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12440 if (!(d & LI_PLCI_B_SKIP_FLAG))
12441 {
12442 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12443 {
12444 if (d & LI_PLCI_B_DISC_FLAG)
12445 {
12446 result[0] = 5;
12447 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12448 result[3] = 2;
12449 PUT_WORD (&result[4], _LI_USER_INITIATED);
12450 }
12451 else
12452 {
12453 result[0] = 7;
12454 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12455 result[3] = 4;
12456 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12457 }
12458 }
12459 else
12460 {
12461 if (d & LI_PLCI_B_DISC_FLAG)
12462 {
12463 result[0] = 9;
12464 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12465 result[3] = 6;
12466 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12467 PUT_WORD (&result[8], _LI_USER_INITIATED);
12468 }
12469 else
12470 {
12471 result[0] = 7;
12472 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12473 result[3] = 4;
12474 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12475 }
12476 }
12477 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12478 "ws", SELECTOR_LINE_INTERCONNECT, result);
12479 }
12480 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12481 0 : plci->li_plci_b_read_pos + 1;
12482 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12483 }
12484}
12485
12486
12487static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length)
12488{
12489 word i, j, ch;
12490 struct xconnect_transfer_address_s s, *p;
12491 DIVA_CAPI_ADAPTER *a;
12492
12493 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12494 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12495
12496 a = plci->adapter;
12497 i = 1;
12498 for (i = 1; i < length; i += 16)
12499 {
12500 s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12501 s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12502 s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12503 ch = msg[i+12] | (msg[i+13] << 8);
12504 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12505 if (!a->li_pri && (plci->li_bchannel_id == 2))
12506 j = 1 - j;
12507 j += a->li_base;
12508 if (ch & XCONNECT_CHANNEL_PORT_PC)
12509 p = &(li_config_table[j].send_pc);
12510 else
12511 p = &(li_config_table[j].send_b);
12512 p->card_address.low = s.card_address.low;
12513 p->card_address.high = s.card_address.high;
12514 p->offset = s.offset;
12515 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12516 }
12517 if (plci->internal_command_queue[0]
12518 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12519 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12520 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12521 {
12522 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12523 if (!plci->internal_command)
12524 next_internal_command (Id, plci);
12525 }
12526 mixer_notify_update (plci, TRUE);
12527}
12528
12529
12530static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length)
12531{
12532
12533 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12534 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12535
12536}
12537
12538
12539static byte mixer_notify_source_removed (PLCI *plci, dword plci_b_id)
12540{
12541 word plci_b_write_pos;
12542
12543 plci_b_write_pos = plci->li_plci_b_write_pos;
12544 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12545 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12546 {
12547 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12548 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12549 (char *)(FILE_), __LINE__));
12550 return (FALSE);
12551 }
12552 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12553 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12554 plci->li_plci_b_write_pos = plci_b_write_pos;
12555 return (TRUE);
12556}
12557
12558
12559static void mixer_remove (PLCI *plci)
12560{
12561 DIVA_CAPI_ADAPTER *a;
12562 PLCI *notify_plci;
12563 dword plci_b_id;
12564 word i, j;
12565
12566 dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12567 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12568 (char *)(FILE_), __LINE__));
12569
12570 a = plci->adapter;
12571 plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12572 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12573 {
12574 if ((plci->li_bchannel_id != 0)
12575 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12576 {
12577 i = a->li_base + (plci->li_bchannel_id - 1);
12578 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12579 {
12580 for (j = 0; j < li_total_channels; j++)
12581 {
12582 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12583 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12584 {
12585 notify_plci = li_config_table[j].plci;
12586 if ((notify_plci != NULL)
12587 && (notify_plci != plci)
12588 && (notify_plci->appl != NULL)
12589 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12590 && (notify_plci->State)
12591 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12592 {
12593 mixer_notify_source_removed (notify_plci, plci_b_id);
12594 }
12595 }
12596 }
12597 mixer_clear_config (plci);
12598 mixer_calculate_coefs (a);
12599 mixer_notify_update (plci, TRUE);
12600 }
12601 li_config_table[i].plci = NULL;
12602 plci->li_bchannel_id = 0;
12603 }
12604 }
12605}
12606
12607
12608/*------------------------------------------------------------------*/
12609/* Echo canceller facilities */
12610/*------------------------------------------------------------------*/
12611
12612
12613static void ec_write_parameters (PLCI *plci)
12614{
12615 word w;
12616 byte parameter_buffer[6];
12617
12618 dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12619 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12620 (char *)(FILE_), __LINE__));
12621
12622 parameter_buffer[0] = 5;
12623 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12624 PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12625 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12626 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12627 PUT_WORD (&parameter_buffer[4], w);
12628 add_p (plci, FTY, parameter_buffer);
12629 sig_req (plci, TEL_CTRL, 0);
12630 send_req (plci);
12631}
12632
12633
12634static void ec_clear_config (PLCI *plci)
12635{
12636
12637 dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12638 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12639 (char *)(FILE_), __LINE__));
12640
12641 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12642 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12643 plci->ec_tail_length = 0;
12644}
12645
12646
12647static void ec_prepare_switch (dword Id, PLCI *plci)
12648{
12649
12650 dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12651 UnMapId (Id), (char *)(FILE_), __LINE__));
12652
12653}
12654
12655
12656static word ec_save_config (dword Id, PLCI *plci, byte Rc)
12657{
12658
12659 dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12660 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12661
12662 return (GOOD);
12663}
12664
12665
12666static word ec_restore_config (dword Id, PLCI *plci, byte Rc)
12667{
12668 word Info;
12669
12670 dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12671 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12672
12673 Info = GOOD;
12674 if (plci->B1_facilities & B1_FACILITY_EC)
12675 {
12676 switch (plci->adjust_b_state)
12677 {
12678 case ADJUST_B_RESTORE_EC_1:
12679 plci->internal_command = plci->adjust_b_command;
12680 if (plci->sig_req)
12681 {
12682 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12683 break;
12684 }
12685 ec_write_parameters (plci);
12686 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12687 break;
12688 case ADJUST_B_RESTORE_EC_2:
12689 if ((Rc != OK) && (Rc != OK_FC))
12690 {
12691 dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12692 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12693 Info = _WRONG_STATE;
12694 break;
12695 }
12696 break;
12697 }
12698 }
12699 return (Info);
12700}
12701
12702
12703static void ec_command (dword Id, PLCI *plci, byte Rc)
12704{
12705 word internal_command, Info;
12706 byte result[8];
12707
12708 dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12709 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12710 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12711
12712 Info = GOOD;
12713 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12714 {
12715 result[0] = 2;
12716 PUT_WORD (&result[1], EC_SUCCESS);
12717 }
12718 else
12719 {
12720 result[0] = 5;
12721 PUT_WORD (&result[1], plci->ec_cmd);
12722 result[3] = 2;
12723 PUT_WORD (&result[4], GOOD);
12724 }
12725 internal_command = plci->internal_command;
12726 plci->internal_command = 0;
12727 switch (plci->ec_cmd)
12728 {
12729 case EC_ENABLE_OPERATION:
12730 case EC_FREEZE_COEFFICIENTS:
12731 case EC_RESUME_COEFFICIENT_UPDATE:
12732 case EC_RESET_COEFFICIENTS:
12733 switch (internal_command)
12734 {
12735 default:
12736 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12737 B1_FACILITY_EC), EC_COMMAND_1);
12738 case EC_COMMAND_1:
12739 if (adjust_b_process (Id, plci, Rc) != GOOD)
12740 {
12741 dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12742 UnMapId (Id), (char *)(FILE_), __LINE__));
12743 Info = _FACILITY_NOT_SUPPORTED;
12744 break;
12745 }
12746 if (plci->internal_command)
12747 return;
12748 case EC_COMMAND_2:
12749 if (plci->sig_req)
12750 {
12751 plci->internal_command = EC_COMMAND_2;
12752 return;
12753 }
12754 plci->internal_command = EC_COMMAND_3;
12755 ec_write_parameters (plci);
12756 return;
12757 case EC_COMMAND_3:
12758 if ((Rc != OK) && (Rc != OK_FC))
12759 {
12760 dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12761 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12762 Info = _FACILITY_NOT_SUPPORTED;
12763 break;
12764 }
12765 break;
12766 }
12767 break;
12768
12769 case EC_DISABLE_OPERATION:
12770 switch (internal_command)
12771 {
12772 default:
12773 case EC_COMMAND_1:
12774 if (plci->B1_facilities & B1_FACILITY_EC)
12775 {
12776 if (plci->sig_req)
12777 {
12778 plci->internal_command = EC_COMMAND_1;
12779 return;
12780 }
12781 plci->internal_command = EC_COMMAND_2;
12782 ec_write_parameters (plci);
12783 return;
12784 }
12785 Rc = OK;
12786 case EC_COMMAND_2:
12787 if ((Rc != OK) && (Rc != OK_FC))
12788 {
12789 dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12790 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12791 Info = _FACILITY_NOT_SUPPORTED;
12792 break;
12793 }
12794 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12795 ~B1_FACILITY_EC), EC_COMMAND_3);
12796 case EC_COMMAND_3:
12797 if (adjust_b_process (Id, plci, Rc) != GOOD)
12798 {
12799 dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12800 UnMapId (Id), (char *)(FILE_), __LINE__));
12801 Info = _FACILITY_NOT_SUPPORTED;
12802 break;
12803 }
12804 if (plci->internal_command)
12805 return;
12806 break;
12807 }
12808 break;
12809 }
12810 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12811 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12812 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12813}
12814
12815
12816static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12817{
12818 word Info;
12819 word opt;
12820 API_PARSE ec_parms[3];
12821 byte result[16];
12822
12823 dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12824 UnMapId (Id), (char *)(FILE_), __LINE__));
12825
12826 Info = GOOD;
12827 result[0] = 0;
12828 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12829 {
12830 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12831 UnMapId (Id), (char *)(FILE_), __LINE__));
12832 Info = _FACILITY_NOT_SUPPORTED;
12833 }
12834 else
12835 {
12836 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12837 {
12838 if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12839 {
12840 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12841 UnMapId (Id), (char *)(FILE_), __LINE__));
12842 Info = _WRONG_MESSAGE_FORMAT;
12843 }
12844 else
12845 {
12846 if (plci == NULL)
12847 {
12848 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12849 UnMapId (Id), (char *)(FILE_), __LINE__));
12850 Info = _WRONG_IDENTIFIER;
12851 }
12852 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12853 {
12854 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12855 UnMapId (Id), (char *)(FILE_), __LINE__));
12856 Info = _WRONG_STATE;
12857 }
12858 else
12859 {
12860 plci->command = 0;
12861 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12862 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12863 result[0] = 2;
12864 PUT_WORD (&result[1], EC_SUCCESS);
12865 if (msg[1].length >= 4)
12866 {
12867 opt = GET_WORD (&ec_parms[0].info[2]);
12868 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12869 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12870 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12871 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12872 if (opt & EC_DETECT_DISABLE_TONE)
12873 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12874 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12875 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12876 if (msg[1].length >= 6)
12877 {
12878 plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12879 }
12880 }
12881 switch (plci->ec_cmd)
12882 {
12883 case EC_ENABLE_OPERATION:
12884 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12885 start_internal_command (Id, plci, ec_command);
12886 return (FALSE);
12887
12888 case EC_DISABLE_OPERATION:
12889 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12890 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12891 LEC_RESET_COEFFICIENTS;
12892 start_internal_command (Id, plci, ec_command);
12893 return (FALSE);
12894
12895 case EC_FREEZE_COEFFICIENTS:
12896 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12897 start_internal_command (Id, plci, ec_command);
12898 return (FALSE);
12899
12900 case EC_RESUME_COEFFICIENT_UPDATE:
12901 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12902 start_internal_command (Id, plci, ec_command);
12903 return (FALSE);
12904
12905 case EC_RESET_COEFFICIENTS:
12906 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12907 start_internal_command (Id, plci, ec_command);
12908 return (FALSE);
12909
12910 default:
12911 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12912 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12913 PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12914 }
12915 }
12916 }
12917 }
12918 else
12919 {
12920 if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12921 {
12922 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12923 UnMapId (Id), (char *)(FILE_), __LINE__));
12924 Info = _WRONG_MESSAGE_FORMAT;
12925 }
12926 else
12927 {
12928 if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12929 {
12930 result[0] = 11;
12931 PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12932 result[3] = 8;
12933 PUT_WORD (&result[4], GOOD);
12934 PUT_WORD (&result[6], 0x0007);
12935 PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12936 PUT_WORD (&result[10], 0);
12937 }
12938 else if (plci == NULL)
12939 {
12940 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12941 UnMapId (Id), (char *)(FILE_), __LINE__));
12942 Info = _WRONG_IDENTIFIER;
12943 }
12944 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12945 {
12946 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12947 UnMapId (Id), (char *)(FILE_), __LINE__));
12948 Info = _WRONG_STATE;
12949 }
12950 else
12951 {
12952 plci->command = 0;
12953 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12954 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12955 result[0] = 5;
12956 PUT_WORD (&result[1], plci->ec_cmd);
12957 result[3] = 2;
12958 PUT_WORD (&result[4], GOOD);
12959 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12960 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12961 plci->ec_tail_length = 0;
12962 if (ec_parms[1].length >= 2)
12963 {
12964 opt = GET_WORD (&ec_parms[1].info[1]);
12965 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12966 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12967 if (opt & EC_DETECT_DISABLE_TONE)
12968 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12969 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12970 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12971 if (ec_parms[1].length >= 4)
12972 {
12973 plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12974 }
12975 }
12976 switch (plci->ec_cmd)
12977 {
12978 case EC_ENABLE_OPERATION:
12979 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12980 start_internal_command (Id, plci, ec_command);
12981 return (FALSE);
12982
12983 case EC_DISABLE_OPERATION:
12984 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12985 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12986 LEC_RESET_COEFFICIENTS;
12987 start_internal_command (Id, plci, ec_command);
12988 return (FALSE);
12989
12990 default:
12991 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12992 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12993 PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12994 }
12995 }
12996 }
12997 }
12998 }
12999 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13000 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13001 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13002 return (FALSE);
13003}
13004
13005
13006static void ec_indication (dword Id, PLCI *plci, byte *msg, word length)
13007{
13008 byte result[8];
13009
13010 dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13011 UnMapId (Id), (char *)(FILE_), __LINE__));
13012
13013 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13014 {
13015 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13016 {
13017 result[0] = 2;
13018 PUT_WORD (&result[1], 0);
13019 switch (msg[1])
13020 {
13021 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13022 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13023 break;
13024 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13025 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13026 break;
13027 case LEC_DISABLE_RELEASED:
13028 PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13029 break;
13030 }
13031 }
13032 else
13033 {
13034 result[0] = 5;
13035 PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13036 result[3] = 2;
13037 PUT_WORD (&result[4], 0);
13038 switch (msg[1])
13039 {
13040 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13041 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13042 break;
13043 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13044 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13045 break;
13046 case LEC_DISABLE_RELEASED:
13047 PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13048 break;
13049 }
13050 }
13051 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13052 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13053 }
13054}
13055
13056
13057
13058/*------------------------------------------------------------------*/
13059/* Advanced voice */
13060/*------------------------------------------------------------------*/
13061
13062static void adv_voice_write_coefs (PLCI *plci, word write_command)
13063{
13064 DIVA_CAPI_ADAPTER *a;
13065 word i;
13066 byte *p;
13067
13068 word w, n, j, k;
13069 byte ch_map[MIXER_CHANNELS_BRI];
13070
13071 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13072
13073 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13074 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13075 (char *)(FILE_), __LINE__, write_command));
13076
13077 a = plci->adapter;
13078 p = coef_buffer + 1;
13079 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13080 i = 0;
13081 while (i + sizeof(word) <= a->adv_voice_coef_length)
13082 {
13083 PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13084 p += 2;
13085 i += 2;
13086 }
13087 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13088 {
13089 PUT_WORD (p, 0x8000);
13090 p += 2;
13091 i += 2;
13092 }
13093
13094 if (!a->li_pri && (plci->li_bchannel_id == 0))
13095 {
13096 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13097 {
13098 plci->li_bchannel_id = 1;
13099 li_config_table[a->li_base].plci = plci;
13100 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13101 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13102 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13103 }
13104 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13105 {
13106 plci->li_bchannel_id = 2;
13107 li_config_table[a->li_base + 1].plci = plci;
13108 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13109 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13110 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13111 }
13112 }
13113 if (!a->li_pri && (plci->li_bchannel_id != 0)
13114 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13115 {
13116 i = a->li_base + (plci->li_bchannel_id - 1);
13117 switch (write_command)
13118 {
13119 case ADV_VOICE_WRITE_ACTIVATION:
13120 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13121 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13122 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13123 {
13124 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13125 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13126 }
13127 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13128 {
13129 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13130 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13131 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13132 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13133 }
13134 mixer_calculate_coefs (a);
13135 li_config_table[i].curchnl = li_config_table[i].channel;
13136 li_config_table[j].curchnl = li_config_table[j].channel;
13137 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13138 li_config_table[k].curchnl = li_config_table[k].channel;
13139 break;
13140
13141 case ADV_VOICE_WRITE_DEACTIVATION:
13142 for (j = 0; j < li_total_channels; j++)
13143 {
13144 li_config_table[i].flag_table[j] = 0;
13145 li_config_table[j].flag_table[i] = 0;
13146 }
13147 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13148 for (j = 0; j < li_total_channels; j++)
13149 {
13150 li_config_table[k].flag_table[j] = 0;
13151 li_config_table[j].flag_table[k] = 0;
13152 }
13153 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13154 {
13155 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13156 for (j = 0; j < li_total_channels; j++)
13157 {
13158 li_config_table[k].flag_table[j] = 0;
13159 li_config_table[j].flag_table[k] = 0;
13160 }
13161 }
13162 mixer_calculate_coefs (a);
13163 break;
13164 }
13165 if (plci->B1_facilities & B1_FACILITY_MIXER)
13166 {
13167 w = 0;
13168 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13169 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13170 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13171 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13172 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13173 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13174 *(p++) = (byte) w;
13175 *(p++) = (byte)(w >> 8);
13176 for (j = 0; j < sizeof(ch_map); j += 2)
13177 {
13178 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13179 ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13180 }
13181 for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
13182 {
13183 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13184 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13185 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13186 {
13187 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13188 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13189 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13190 }
13191 else
13192 {
13193 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13194 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13195 }
13196 }
13197 }
13198 else
13199 {
13200 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13201 *(p++) = a->adv_voice_coef_buffer[i];
13202 }
13203 }
13204 else
13205
13206 {
13207 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13208 *(p++) = a->adv_voice_coef_buffer[i];
13209 }
13210 coef_buffer[0] = (p - coef_buffer) - 1;
13211 add_p (plci, FTY, coef_buffer);
13212 sig_req (plci, TEL_CTRL, 0);
13213 send_req (plci);
13214}
13215
13216
13217static void adv_voice_clear_config (PLCI *plci)
13218{
13219 DIVA_CAPI_ADAPTER *a;
13220
13221 word i, j;
13222
13223
13224 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13225 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13226 (char *)(FILE_), __LINE__));
13227
13228 a = plci->adapter;
13229 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13230 {
13231 a->adv_voice_coef_length = 0;
13232
13233 if (!a->li_pri && (plci->li_bchannel_id != 0)
13234 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13235 {
13236 i = a->li_base + (plci->li_bchannel_id - 1);
13237 li_config_table[i].curchnl = 0;
13238 li_config_table[i].channel = 0;
13239 li_config_table[i].chflags = 0;
13240 for (j = 0; j < li_total_channels; j++)
13241 {
13242 li_config_table[i].flag_table[j] = 0;
13243 li_config_table[j].flag_table[i] = 0;
13244 li_config_table[i].coef_table[j] = 0;
13245 li_config_table[j].coef_table[i] = 0;
13246 }
13247 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13248 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13249 li_config_table[i].curchnl = 0;
13250 li_config_table[i].channel = 0;
13251 li_config_table[i].chflags = 0;
13252 for (j = 0; j < li_total_channels; j++)
13253 {
13254 li_config_table[i].flag_table[j] = 0;
13255 li_config_table[j].flag_table[i] = 0;
13256 li_config_table[i].coef_table[j] = 0;
13257 li_config_table[j].coef_table[i] = 0;
13258 }
13259 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13260 {
13261 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13262 li_config_table[i].curchnl = 0;
13263 li_config_table[i].channel = 0;
13264 li_config_table[i].chflags = 0;
13265 for (j = 0; j < li_total_channels; j++)
13266 {
13267 li_config_table[i].flag_table[j] = 0;
13268 li_config_table[j].flag_table[i] = 0;
13269 li_config_table[i].coef_table[j] = 0;
13270 li_config_table[j].coef_table[i] = 0;
13271 }
13272 }
13273 }
13274
13275 }
13276}
13277
13278
13279static void adv_voice_prepare_switch (dword Id, PLCI *plci)
13280{
13281
13282 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13283 UnMapId (Id), (char *)(FILE_), __LINE__));
13284
13285}
13286
13287
13288static word adv_voice_save_config (dword Id, PLCI *plci, byte Rc)
13289{
13290
13291 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13292 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13293
13294 return (GOOD);
13295}
13296
13297
13298static word adv_voice_restore_config (dword Id, PLCI *plci, byte Rc)
13299{
13300 DIVA_CAPI_ADAPTER *a;
13301 word Info;
13302
13303 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13304 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13305
13306 Info = GOOD;
13307 a = plci->adapter;
13308 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13309 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13310 {
13311 switch (plci->adjust_b_state)
13312 {
13313 case ADJUST_B_RESTORE_VOICE_1:
13314 plci->internal_command = plci->adjust_b_command;
13315 if (plci->sig_req)
13316 {
13317 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13318 break;
13319 }
13320 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13321 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13322 break;
13323 case ADJUST_B_RESTORE_VOICE_2:
13324 if ((Rc != OK) && (Rc != OK_FC))
13325 {
13326 dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13327 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13328 Info = _WRONG_STATE;
13329 break;
13330 }
13331 break;
13332 }
13333 }
13334 return (Info);
13335}
13336
13337
13338
13339
13340/*------------------------------------------------------------------*/
13341/* B1 resource switching */
13342/*------------------------------------------------------------------*/
13343
13344static byte b1_facilities_table[] =
13345{
13346 0x00, /* 0 No bchannel resources */
13347 0x00, /* 1 Codec (automatic law) */
13348 0x00, /* 2 Codec (A-law) */
13349 0x00, /* 3 Codec (y-law) */
13350 0x00, /* 4 HDLC for X.21 */
13351 0x00, /* 5 HDLC */
13352 0x00, /* 6 External Device 0 */
13353 0x00, /* 7 External Device 1 */
13354 0x00, /* 8 HDLC 56k */
13355 0x00, /* 9 Transparent */
13356 0x00, /* 10 Loopback to network */
13357 0x00, /* 11 Test pattern to net */
13358 0x00, /* 12 Rate adaptation sync */
13359 0x00, /* 13 Rate adaptation async */
13360 0x00, /* 14 R-Interface */
13361 0x00, /* 15 HDLC 128k leased line */
13362 0x00, /* 16 FAX */
13363 0x00, /* 17 Modem async */
13364 0x00, /* 18 Modem sync HDLC */
13365 0x00, /* 19 V.110 async HDLC */
13366 0x12, /* 20 Adv voice (Trans,mixer) */
13367 0x00, /* 21 Codec connected to IC */
13368 0x0c, /* 22 Trans,DTMF */
13369 0x1e, /* 23 Trans,DTMF+mixer */
13370 0x1f, /* 24 Trans,DTMF+mixer+local */
13371 0x13, /* 25 Trans,mixer+local */
13372 0x12, /* 26 HDLC,mixer */
13373 0x12, /* 27 HDLC 56k,mixer */
13374 0x2c, /* 28 Trans,LEC+DTMF */
13375 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13376 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13377 0x2c, /* 31 RTP,LEC+DTMF */
13378 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13379 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13380 0x00, /* 34 Signaling task */
13381 0x00, /* 35 PIAFS */
13382 0x0c, /* 36 Trans,DTMF+TONE */
13383 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13384 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13385};
13386
13387
13388static word get_b1_facilities (PLCI * plci, byte b1_resource)
13389{
13390 word b1_facilities;
13391
13392 b1_facilities = b1_facilities_table[b1_resource];
13393 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13394 {
13395
13396 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13397 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13398
13399 {
13400 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13401 b1_facilities |= B1_FACILITY_DTMFX;
13402 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13403 b1_facilities |= B1_FACILITY_DTMFR;
13404 }
13405 }
13406 if ((b1_resource == 17) || (b1_resource == 18))
13407 {
13408 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13409 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13410 }
13411/*
13412 dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13413 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13414 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13415*/
13416 return (b1_facilities);
13417}
13418
13419
13420static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities)
13421{
13422 byte b;
13423
13424 switch (b1_resource)
13425 {
13426 case 5:
13427 case 26:
13428 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13429 b = 26;
13430 else
13431 b = 5;
13432 break;
13433
13434 case 8:
13435 case 27:
13436 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13437 b = 27;
13438 else
13439 b = 8;
13440 break;
13441
13442 case 9:
13443 case 20:
13444 case 22:
13445 case 23:
13446 case 24:
13447 case 25:
13448 case 28:
13449 case 29:
13450 case 30:
13451 case 36:
13452 case 37:
13453 case 38:
13454 if (b1_facilities & B1_FACILITY_EC)
13455 {
13456 if (b1_facilities & B1_FACILITY_LOCAL)
13457 b = 30;
13458 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13459 b = 29;
13460 else
13461 b = 28;
13462 }
13463
13464 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13465 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13466 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13467 {
13468 if (b1_facilities & B1_FACILITY_LOCAL)
13469 b = 38;
13470 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13471 b = 37;
13472 else
13473 b = 36;
13474 }
13475
13476 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13477 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13478 || ((b1_facilities & B1_FACILITY_DTMFR)
13479 && ((b1_facilities & B1_FACILITY_MIXER)
13480 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13481 || ((b1_facilities & B1_FACILITY_DTMFX)
13482 && ((b1_facilities & B1_FACILITY_MIXER)
13483 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13484 {
13485 if (b1_facilities & B1_FACILITY_LOCAL)
13486 b = 24;
13487 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13488 b = 23;
13489 else
13490 b = 22;
13491 }
13492 else
13493 {
13494 if (b1_facilities & B1_FACILITY_LOCAL)
13495 b = 25;
13496 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13497 b = 20;
13498 else
13499 b = 9;
13500 }
13501 break;
13502
13503 case 31:
13504 case 32:
13505 case 33:
13506 if (b1_facilities & B1_FACILITY_LOCAL)
13507 b = 33;
13508 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13509 b = 32;
13510 else
13511 b = 31;
13512 break;
13513
13514 default:
13515 b = b1_resource;
13516 }
13517 dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13518 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13519 (char *)(FILE_), __LINE__,
13520 b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13521 return (b);
13522}
13523
13524
13525static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13526{
13527 word removed_facilities;
13528
13529 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13530 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13531 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13532 new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13533
13534 new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13535 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13536
13537 if (removed_facilities & B1_FACILITY_EC)
13538 ec_clear_config (plci);
13539
13540
13541 if (removed_facilities & B1_FACILITY_DTMFR)
13542 {
13543 dtmf_rec_clear_config (plci);
13544 dtmf_parameter_clear_config (plci);
13545 }
13546 if (removed_facilities & B1_FACILITY_DTMFX)
13547 dtmf_send_clear_config (plci);
13548
13549
13550 if (removed_facilities & B1_FACILITY_MIXER)
13551 mixer_clear_config (plci);
13552
13553 if (removed_facilities & B1_FACILITY_VOICE)
13554 adv_voice_clear_config (plci);
13555 plci->B1_facilities = new_b1_facilities;
13556}
13557
13558
13559static void adjust_b_clear (PLCI *plci)
13560{
13561
13562 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13563 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13564 (char *)(FILE_), __LINE__));
13565
13566 plci->adjust_b_restore = FALSE;
13567}
13568
13569
13570static word adjust_b_process (dword Id, PLCI *plci, byte Rc)
13571{
13572 word Info;
13573 byte b1_resource;
13574 NCCI * ncci_ptr;
13575 API_PARSE bp[2];
13576
13577 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13578 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13579
13580 Info = GOOD;
13581 switch (plci->adjust_b_state)
13582 {
13583 case ADJUST_B_START:
13584 if ((plci->adjust_b_parms_msg == NULL)
13585 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13586 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13587 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13588 {
13589 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13590 0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13591 if (b1_resource == plci->B1_resource)
13592 {
13593 adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13594 break;
13595 }
13596 if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13597 {
13598 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13599 UnMapId (Id), (char *)(FILE_), __LINE__,
13600 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13601 Info = _WRONG_STATE;
13602 break;
13603 }
13604 }
13605 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13606 {
13607
13608 mixer_prepare_switch (Id, plci);
13609
13610
13611 dtmf_prepare_switch (Id, plci);
13612 dtmf_parameter_prepare_switch (Id, plci);
13613
13614
13615 ec_prepare_switch (Id, plci);
13616
13617 adv_voice_prepare_switch (Id, plci);
13618 }
13619 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13620 Rc = OK;
13621 case ADJUST_B_SAVE_MIXER_1:
13622 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13623 {
13624
13625 Info = mixer_save_config (Id, plci, Rc);
13626 if ((Info != GOOD) || plci->internal_command)
13627 break;
13628
13629 }
13630 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13631 Rc = OK;
13632 case ADJUST_B_SAVE_DTMF_1:
13633 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13634 {
13635
13636 Info = dtmf_save_config (Id, plci, Rc);
13637 if ((Info != GOOD) || plci->internal_command)
13638 break;
13639
13640 }
13641 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13642 case ADJUST_B_REMOVE_L23_1:
13643 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13644 && plci->NL.Id && !plci->nl_remove_id)
13645 {
13646 plci->internal_command = plci->adjust_b_command;
13647 if (plci->adjust_b_ncci != 0)
13648 {
13649 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13650 while (ncci_ptr->data_pending)
13651 {
13652 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13653 data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13654 }
13655 while (ncci_ptr->data_ack_pending)
13656 data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13657 }
13658 nl_req_ncci (plci, REMOVE,
13659 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13660 send_req (plci);
13661 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13662 break;
13663 }
13664 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13665 Rc = OK;
13666 case ADJUST_B_REMOVE_L23_2:
13667 if ((Rc != OK) && (Rc != OK_FC))
13668 {
13669 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13670 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13671 Info = _WRONG_STATE;
13672 break;
13673 }
13674 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13675 {
13676 if (plci_nl_busy (plci))
13677 {
13678 plci->internal_command = plci->adjust_b_command;
13679 break;
13680 }
13681 }
13682 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13683 Rc = OK;
13684 case ADJUST_B_SAVE_EC_1:
13685 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13686 {
13687
13688 Info = ec_save_config (Id, plci, Rc);
13689 if ((Info != GOOD) || plci->internal_command)
13690 break;
13691
13692 }
13693 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13694 Rc = OK;
13695 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13696 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13697 {
13698
13699 Info = dtmf_parameter_save_config (Id, plci, Rc);
13700 if ((Info != GOOD) || plci->internal_command)
13701 break;
13702
13703 }
13704 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13705 Rc = OK;
13706 case ADJUST_B_SAVE_VOICE_1:
13707 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13708 {
13709 Info = adv_voice_save_config (Id, plci, Rc);
13710 if ((Info != GOOD) || plci->internal_command)
13711 break;
13712 }
13713 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13714 case ADJUST_B_SWITCH_L1_1:
13715 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13716 {
13717 if (plci->sig_req)
13718 {
13719 plci->internal_command = plci->adjust_b_command;
13720 break;
13721 }
13722 if (plci->adjust_b_parms_msg != NULL)
13723 api_load_msg (plci->adjust_b_parms_msg, bp);
13724 else
13725 api_load_msg (&plci->B_protocol, bp);
13726 Info = add_b1 (plci, bp,
13727 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13728 plci->adjust_b_facilities);
13729 if (Info != GOOD)
13730 {
13731 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13732 UnMapId (Id), (char *)(FILE_), __LINE__,
13733 plci->B1_resource, plci->adjust_b_facilities));
13734 break;
13735 }
13736 plci->internal_command = plci->adjust_b_command;
13737 sig_req (plci, RESOURCES, 0);
13738 send_req (plci);
13739 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13740 break;
13741 }
13742 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13743 Rc = OK;
13744 case ADJUST_B_SWITCH_L1_2:
13745 if ((Rc != OK) && (Rc != OK_FC))
13746 {
13747 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13748 UnMapId (Id), (char *)(FILE_), __LINE__,
13749 Rc, plci->B1_resource, plci->adjust_b_facilities));
13750 Info = _WRONG_STATE;
13751 break;
13752 }
13753 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13754 Rc = OK;
13755 case ADJUST_B_RESTORE_VOICE_1:
13756 case ADJUST_B_RESTORE_VOICE_2:
13757 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13758 {
13759 Info = adv_voice_restore_config (Id, plci, Rc);
13760 if ((Info != GOOD) || plci->internal_command)
13761 break;
13762 }
13763 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13764 Rc = OK;
13765 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13766 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13767 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13768 {
13769
13770 Info = dtmf_parameter_restore_config (Id, plci, Rc);
13771 if ((Info != GOOD) || plci->internal_command)
13772 break;
13773
13774 }
13775 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13776 Rc = OK;
13777 case ADJUST_B_RESTORE_EC_1:
13778 case ADJUST_B_RESTORE_EC_2:
13779 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13780 {
13781
13782 Info = ec_restore_config (Id, plci, Rc);
13783 if ((Info != GOOD) || plci->internal_command)
13784 break;
13785
13786 }
13787 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13788 case ADJUST_B_ASSIGN_L23_1:
13789 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13790 {
13791 if (plci_nl_busy (plci))
13792 {
13793 plci->internal_command = plci->adjust_b_command;
13794 break;
13795 }
13796 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13797 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13798 if (plci->adjust_b_parms_msg != NULL)
13799 api_load_msg (plci->adjust_b_parms_msg, bp);
13800 else
13801 api_load_msg (&plci->B_protocol, bp);
13802 Info = add_b23 (plci, bp);
13803 if (Info != GOOD)
13804 {
13805 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13806 UnMapId (Id), (char *)(FILE_), __LINE__, Info));
13807 break;
13808 }
13809 plci->internal_command = plci->adjust_b_command;
13810 nl_req_ncci (plci, ASSIGN, 0);
13811 send_req (plci);
13812 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13813 break;
13814 }
13815 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13816 Rc = ASSIGN_OK;
13817 case ADJUST_B_ASSIGN_L23_2:
13818 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13819 {
13820 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13821 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13822 Info = _WRONG_STATE;
13823 break;
13824 }
13825 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13826 {
13827 if (Rc != ASSIGN_OK)
13828 {
13829 plci->internal_command = plci->adjust_b_command;
13830 break;
13831 }
13832 }
13833 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13834 {
13835 plci->adjust_b_restore = TRUE;
13836 break;
13837 }
13838 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13839 case ADJUST_B_CONNECT_1:
13840 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13841 {
13842 plci->internal_command = plci->adjust_b_command;
13843 if (plci_nl_busy (plci))
13844 break;
13845 nl_req_ncci (plci, N_CONNECT, 0);
13846 send_req (plci);
13847 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13848 break;
13849 }
13850 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13851 Rc = OK;
13852 case ADJUST_B_CONNECT_2:
13853 case ADJUST_B_CONNECT_3:
13854 case ADJUST_B_CONNECT_4:
13855 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13856 {
13857 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13858 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13859 Info = _WRONG_STATE;
13860 break;
13861 }
13862 if (Rc == OK)
13863 {
13864 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13865 {
13866 get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13867 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13868 }
13869 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13870 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13871 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13872 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13873 }
13874 else if (Rc == 0)
13875 {
13876 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13877 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13878 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13879 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13880 }
13881 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13882 {
13883 plci->internal_command = plci->adjust_b_command;
13884 break;
13885 }
13886 Rc = OK;
13887 case ADJUST_B_RESTORE_DTMF_1:
13888 case ADJUST_B_RESTORE_DTMF_2:
13889 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13890 {
13891
13892 Info = dtmf_restore_config (Id, plci, Rc);
13893 if ((Info != GOOD) || plci->internal_command)
13894 break;
13895
13896 }
13897 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13898 Rc = OK;
13899 case ADJUST_B_RESTORE_MIXER_1:
13900 case ADJUST_B_RESTORE_MIXER_2:
13901 case ADJUST_B_RESTORE_MIXER_3:
13902 case ADJUST_B_RESTORE_MIXER_4:
13903 case ADJUST_B_RESTORE_MIXER_5:
13904 case ADJUST_B_RESTORE_MIXER_6:
13905 case ADJUST_B_RESTORE_MIXER_7:
13906 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13907 {
13908
13909 Info = mixer_restore_config (Id, plci, Rc);
13910 if ((Info != GOOD) || plci->internal_command)
13911 break;
13912
13913 }
13914 plci->adjust_b_state = ADJUST_B_END;
13915 case ADJUST_B_END:
13916 break;
13917 }
13918 return (Info);
13919}
13920
13921
13922static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13923{
13924
13925 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13926 UnMapId (Id), (char *)(FILE_), __LINE__,
13927 plci->B1_resource, b1_facilities));
13928
13929 plci->adjust_b_parms_msg = bp_msg;
13930 plci->adjust_b_facilities = b1_facilities;
13931 plci->adjust_b_command = internal_command;
13932 plci->adjust_b_ncci = (word)(Id >> 16);
13933 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13934 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13935 else
13936 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13937 plci->adjust_b_state = ADJUST_B_START;
13938 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13939 UnMapId (Id), (char *)(FILE_), __LINE__,
13940 plci->B1_resource, b1_facilities));
13941}
13942
13943
13944static void adjust_b_restore (dword Id, PLCI *plci, byte Rc)
13945{
13946 word internal_command;
13947
13948 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13949 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13950
13951 internal_command = plci->internal_command;
13952 plci->internal_command = 0;
13953 switch (internal_command)
13954 {
13955 default:
13956 plci->command = 0;
13957 if (plci->req_in != 0)
13958 {
13959 plci->internal_command = ADJUST_B_RESTORE_1;
13960 break;
13961 }
13962 Rc = OK;
13963 case ADJUST_B_RESTORE_1:
13964 if ((Rc != OK) && (Rc != OK_FC))
13965 {
13966 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13967 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13968 }
13969 plci->adjust_b_parms_msg = NULL;
13970 plci->adjust_b_facilities = plci->B1_facilities;
13971 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13972 plci->adjust_b_ncci = (word)(Id >> 16);
13973 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13974 plci->adjust_b_state = ADJUST_B_START;
13975 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13976 UnMapId (Id), (char *)(FILE_), __LINE__));
13977 case ADJUST_B_RESTORE_2:
13978 if (adjust_b_process (Id, plci, Rc) != GOOD)
13979 {
13980 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
13981 UnMapId (Id), (char *)(FILE_), __LINE__));
13982 }
13983 if (plci->internal_command)
13984 break;
13985 break;
13986 }
13987}
13988
13989
13990static void reset_b3_command (dword Id, PLCI *plci, byte Rc)
13991{
13992 word Info;
13993 word internal_command;
13994
13995 dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
13996 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13997
13998 Info = GOOD;
13999 internal_command = plci->internal_command;
14000 plci->internal_command = 0;
14001 switch (internal_command)
14002 {
14003 default:
14004 plci->command = 0;
14005 plci->adjust_b_parms_msg = NULL;
14006 plci->adjust_b_facilities = plci->B1_facilities;
14007 plci->adjust_b_command = RESET_B3_COMMAND_1;
14008 plci->adjust_b_ncci = (word)(Id >> 16);
14009 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14010 plci->adjust_b_state = ADJUST_B_START;
14011 dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14012 UnMapId (Id), (char *)(FILE_), __LINE__));
14013 case RESET_B3_COMMAND_1:
14014 Info = adjust_b_process (Id, plci, Rc);
14015 if (Info != GOOD)
14016 {
14017 dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14018 UnMapId (Id), (char *)(FILE_), __LINE__));
14019 break;
14020 }
14021 if (plci->internal_command)
14022 return;
14023 break;
14024 }
14025/* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14026 sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14027}
14028
14029
14030static void select_b_command (dword Id, PLCI *plci, byte Rc)
14031{
14032 word Info;
14033 word internal_command;
14034 byte esc_chi[3];
14035
14036 dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14037 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14038
14039 Info = GOOD;
14040 internal_command = plci->internal_command;
14041 plci->internal_command = 0;
14042 switch (internal_command)
14043 {
14044 default:
14045 plci->command = 0;
14046 plci->adjust_b_parms_msg = &plci->saved_msg;
14047 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14048 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14049 else
14050 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14051 plci->adjust_b_command = SELECT_B_COMMAND_1;
14052 plci->adjust_b_ncci = (word)(Id >> 16);
14053 if (plci->saved_msg.parms[0].length == 0)
14054 {
14055 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14056 ADJUST_B_MODE_NO_RESOURCE;
14057 }
14058 else
14059 {
14060 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14061 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14062 }
14063 plci->adjust_b_state = ADJUST_B_START;
14064 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14065 UnMapId (Id), (char *)(FILE_), __LINE__));
14066 case SELECT_B_COMMAND_1:
14067 Info = adjust_b_process (Id, plci, Rc);
14068 if (Info != GOOD)
14069 {
14070 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14071 UnMapId (Id), (char *)(FILE_), __LINE__));
14072 break;
14073 }
14074 if (plci->internal_command)
14075 return;
14076 if (plci->tel == ADV_VOICE)
14077 {
14078 esc_chi[0] = 0x02;
14079 esc_chi[1] = 0x18;
14080 esc_chi[2] = plci->b_channel;
14081 SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14082 }
14083 break;
14084 }
14085 sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14086}
14087
14088
14089static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc)
14090{
14091 word Info;
14092 word internal_command;
14093
14094 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14095 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14096
14097 Info = GOOD;
14098 internal_command = plci->internal_command;
14099 plci->internal_command = 0;
14100 switch (internal_command)
14101 {
14102 default:
14103 plci->command = 0;
14104 case FAX_CONNECT_ACK_COMMAND_1:
14105 if (plci_nl_busy (plci))
14106 {
14107 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14108 return;
14109 }
14110 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14111 plci->NData[0].P = plci->fax_connect_info_buffer;
14112 plci->NData[0].PLength = plci->fax_connect_info_length;
14113 plci->NL.X = plci->NData;
14114 plci->NL.ReqCh = 0;
14115 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14116 plci->adapter->request (&plci->NL);
14117 return;
14118 case FAX_CONNECT_ACK_COMMAND_2:
14119 if ((Rc != OK) && (Rc != OK_FC))
14120 {
14121 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14122 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14123 break;
14124 }
14125 }
14126 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14127 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14128 {
14129 if (plci->B3_prot == 4)
14130 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14131 else
14132 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14133 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14134 }
14135}
14136
14137
14138static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc)
14139{
14140 word Info;
14141 word internal_command;
14142
14143 dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14144 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14145
14146 Info = GOOD;
14147 internal_command = plci->internal_command;
14148 plci->internal_command = 0;
14149 switch (internal_command)
14150 {
14151 default:
14152 plci->command = 0;
14153 case FAX_EDATA_ACK_COMMAND_1:
14154 if (plci_nl_busy (plci))
14155 {
14156 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14157 return;
14158 }
14159 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14160 plci->NData[0].P = plci->fax_connect_info_buffer;
14161 plci->NData[0].PLength = plci->fax_edata_ack_length;
14162 plci->NL.X = plci->NData;
14163 plci->NL.ReqCh = 0;
14164 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14165 plci->adapter->request (&plci->NL);
14166 return;
14167 case FAX_EDATA_ACK_COMMAND_2:
14168 if ((Rc != OK) && (Rc != OK_FC))
14169 {
14170 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14171 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14172 break;
14173 }
14174 }
14175}
14176
14177
14178static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc)
14179{
14180 word Info;
14181 word internal_command;
14182
14183 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14184 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14185
14186 Info = GOOD;
14187 internal_command = plci->internal_command;
14188 plci->internal_command = 0;
14189 switch (internal_command)
14190 {
14191 default:
14192 plci->command = 0;
14193 case FAX_CONNECT_INFO_COMMAND_1:
14194 if (plci_nl_busy (plci))
14195 {
14196 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14197 return;
14198 }
14199 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14200 plci->NData[0].P = plci->fax_connect_info_buffer;
14201 plci->NData[0].PLength = plci->fax_connect_info_length;
14202 plci->NL.X = plci->NData;
14203 plci->NL.ReqCh = 0;
14204 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14205 plci->adapter->request (&plci->NL);
14206 return;
14207 case FAX_CONNECT_INFO_COMMAND_2:
14208 if ((Rc != OK) && (Rc != OK_FC))
14209 {
14210 dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14211 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14212 Info = _WRONG_STATE;
14213 break;
14214 }
14215 if (plci_nl_busy (plci))
14216 {
14217 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14218 return;
14219 }
14220 plci->command = _CONNECT_B3_R;
14221 nl_req_ncci (plci, N_CONNECT, 0);
14222 send_req (plci);
14223 return;
14224 }
14225 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14226}
14227
14228
14229static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc)
14230{
14231 word Info;
14232 word internal_command;
14233
14234 dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14235 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14236
14237 Info = GOOD;
14238 internal_command = plci->internal_command;
14239 plci->internal_command = 0;
14240 switch (internal_command)
14241 {
14242 default:
14243 plci->command = 0;
14244 plci->adjust_b_parms_msg = NULL;
14245 plci->adjust_b_facilities = plci->B1_facilities;
14246 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14247 plci->adjust_b_ncci = (word)(Id >> 16);
14248 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14249 plci->adjust_b_state = ADJUST_B_START;
14250 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14251 UnMapId (Id), (char *)(FILE_), __LINE__));
14252 case FAX_ADJUST_B23_COMMAND_1:
14253 Info = adjust_b_process (Id, plci, Rc);
14254 if (Info != GOOD)
14255 {
14256 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14257 UnMapId (Id), (char *)(FILE_), __LINE__));
14258 break;
14259 }
14260 if (plci->internal_command)
14261 return;
14262 case FAX_ADJUST_B23_COMMAND_2:
14263 if (plci_nl_busy (plci))
14264 {
14265 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14266 return;
14267 }
14268 plci->command = _CONNECT_B3_R;
14269 nl_req_ncci (plci, N_CONNECT, 0);
14270 send_req (plci);
14271 return;
14272 }
14273 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14274}
14275
14276
14277static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc)
14278{
14279 word internal_command;
14280
14281 dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14282 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14283
14284 internal_command = plci->internal_command;
14285 plci->internal_command = 0;
14286 switch (internal_command)
14287 {
14288 default:
14289 plci->command = 0;
14290 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14291 return;
14292 case FAX_DISCONNECT_COMMAND_1:
14293 case FAX_DISCONNECT_COMMAND_2:
14294 case FAX_DISCONNECT_COMMAND_3:
14295 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14296 {
14297 dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14298 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14299 break;
14300 }
14301 if (Rc == OK)
14302 {
14303 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14304 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14305 {
14306 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14307 }
14308 }
14309 else if (Rc == 0)
14310 {
14311 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14312 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14313 }
14314 return;
14315 }
14316}
14317
14318
14319
14320static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc)
14321{
14322 word Info;
14323 word internal_command;
14324
14325 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14326 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14327
14328 Info = GOOD;
14329 internal_command = plci->internal_command;
14330 plci->internal_command = 0;
14331 switch (internal_command)
14332 {
14333 default:
14334 plci->command = 0;
14335 case RTP_CONNECT_B3_REQ_COMMAND_1:
14336 if (plci_nl_busy (plci))
14337 {
14338 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14339 return;
14340 }
14341 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14342 nl_req_ncci (plci, N_CONNECT, 0);
14343 send_req (plci);
14344 return;
14345 case RTP_CONNECT_B3_REQ_COMMAND_2:
14346 if ((Rc != OK) && (Rc != OK_FC))
14347 {
14348 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14349 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14350 Info = _WRONG_STATE;
14351 break;
14352 }
14353 if (plci_nl_busy (plci))
14354 {
14355 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14356 return;
14357 }
14358 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14359 plci->NData[0].PLength = plci->internal_req_buffer[0];
14360 plci->NData[0].P = plci->internal_req_buffer + 1;
14361 plci->NL.X = plci->NData;
14362 plci->NL.ReqCh = 0;
14363 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14364 plci->adapter->request (&plci->NL);
14365 break;
14366 case RTP_CONNECT_B3_REQ_COMMAND_3:
14367 return;
14368 }
14369 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14370}
14371
14372
14373static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc)
14374{
14375 word Info;
14376 word internal_command;
14377
14378 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14379 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14380
14381 Info = GOOD;
14382 internal_command = plci->internal_command;
14383 plci->internal_command = 0;
14384 switch (internal_command)
14385 {
14386 default:
14387 plci->command = 0;
14388 case RTP_CONNECT_B3_RES_COMMAND_1:
14389 if (plci_nl_busy (plci))
14390 {
14391 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14392 return;
14393 }
14394 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14395 nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14396 send_req (plci);
14397 return;
14398 case RTP_CONNECT_B3_RES_COMMAND_2:
14399 if ((Rc != OK) && (Rc != OK_FC))
14400 {
14401 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14402 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14403 Info = _WRONG_STATE;
14404 break;
14405 }
14406 if (plci_nl_busy (plci))
14407 {
14408 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14409 return;
14410 }
14411 sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14412 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14413 plci->NData[0].PLength = plci->internal_req_buffer[0];
14414 plci->NData[0].P = plci->internal_req_buffer + 1;
14415 plci->NL.X = plci->NData;
14416 plci->NL.ReqCh = 0;
14417 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14418 plci->adapter->request (&plci->NL);
14419 return;
14420 case RTP_CONNECT_B3_RES_COMMAND_3:
14421 return;
14422 }
14423}
14424
14425
14426
14427static void hold_save_command (dword Id, PLCI *plci, byte Rc)
14428{
14429 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14430 word Info;
14431 word internal_command;
14432
14433 dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14434 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14435
14436 Info = GOOD;
14437 internal_command = plci->internal_command;
14438 plci->internal_command = 0;
14439 switch (internal_command)
14440 {
14441 default:
14442 if (!plci->NL.Id)
14443 break;
14444 plci->command = 0;
14445 plci->adjust_b_parms_msg = NULL;
14446 plci->adjust_b_facilities = plci->B1_facilities;
14447 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14448 plci->adjust_b_ncci = (word)(Id >> 16);
14449 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14450 plci->adjust_b_state = ADJUST_B_START;
14451 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14452 UnMapId (Id), (char *)(FILE_), __LINE__));
14453 case HOLD_SAVE_COMMAND_1:
14454 Info = adjust_b_process (Id, plci, Rc);
14455 if (Info != GOOD)
14456 {
14457 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14458 UnMapId (Id), (char *)(FILE_), __LINE__));
14459 break;
14460 }
14461 if (plci->internal_command)
14462 return;
14463 }
14464 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14465}
14466
14467
14468static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc)
14469{
14470 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14471 word Info;
14472 word internal_command;
14473
14474 dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14475 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14476
14477 Info = GOOD;
14478 internal_command = plci->internal_command;
14479 plci->internal_command = 0;
14480 switch (internal_command)
14481 {
14482 default:
14483 plci->command = 0;
14484 plci->adjust_b_parms_msg = NULL;
14485 plci->adjust_b_facilities = plci->B1_facilities;
14486 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14487 plci->adjust_b_ncci = (word)(Id >> 16);
14488 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14489 plci->adjust_b_state = ADJUST_B_START;
14490 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14491 UnMapId (Id), (char *)(FILE_), __LINE__));
14492 case RETRIEVE_RESTORE_COMMAND_1:
14493 Info = adjust_b_process (Id, plci, Rc);
14494 if (Info != GOOD)
14495 {
14496 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14497 UnMapId (Id), (char *)(FILE_), __LINE__));
14498 break;
14499 }
14500 if (plci->internal_command)
14501 return;
14502 }
14503 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14504}
14505
14506
14507static void init_b1_config (PLCI *plci)
14508{
14509
14510 dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14511 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14512 (char *)(FILE_), __LINE__));
14513
14514 plci->B1_resource = 0;
14515 plci->B1_facilities = 0;
14516
14517 plci->li_bchannel_id = 0;
14518 mixer_clear_config (plci);
14519
14520
14521 ec_clear_config (plci);
14522
14523
14524 dtmf_rec_clear_config (plci);
14525 dtmf_send_clear_config (plci);
14526 dtmf_parameter_clear_config (plci);
14527
14528 adv_voice_clear_config (plci);
14529 adjust_b_clear (plci);
14530}
14531
14532
14533static void clear_b1_config (PLCI *plci)
14534{
14535
14536 dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14537 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14538 (char *)(FILE_), __LINE__));
14539
14540 adv_voice_clear_config (plci);
14541 adjust_b_clear (plci);
14542
14543 ec_clear_config (plci);
14544
14545
14546 dtmf_rec_clear_config (plci);
14547 dtmf_send_clear_config (plci);
14548 dtmf_parameter_clear_config (plci);
14549
14550
14551 if ((plci->li_bchannel_id != 0)
14552 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14553 {
14554 mixer_clear_config (plci);
14555 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14556 plci->li_bchannel_id = 0;
14557 }
14558
14559 plci->B1_resource = 0;
14560 plci->B1_facilities = 0;
14561}
14562
14563
14564/* -----------------------------------------------------------------
14565 XON protocol local helpers
14566 ----------------------------------------------------------------- */
14567static void channel_flow_control_remove (PLCI * plci) {
14568 DIVA_CAPI_ADAPTER * a = plci->adapter;
14569 word i;
14570 for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14571 if (a->ch_flow_plci[i] == plci->Id) {
14572 a->ch_flow_plci[i] = 0;
14573 a->ch_flow_control[i] = 0;
14574 }
14575 }
14576}
14577
14578static void channel_x_on (PLCI * plci, byte ch) {
14579 DIVA_CAPI_ADAPTER * a = plci->adapter;
14580 if (a->ch_flow_control[ch] & N_XON_SENT) {
14581 a->ch_flow_control[ch] &= ~N_XON_SENT;
14582 }
14583}
14584
14585static void channel_x_off (PLCI * plci, byte ch, byte flag) {
14586 DIVA_CAPI_ADAPTER * a = plci->adapter;
14587 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14588 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14589 a->ch_flow_plci[ch] = plci->Id;
14590 a->ch_flow_control_pending++;
14591 }
14592}
14593
14594static void channel_request_xon (PLCI * plci, byte ch) {
14595 DIVA_CAPI_ADAPTER * a = plci->adapter;
14596
14597 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14598 a->ch_flow_control[ch] |= N_XON_REQ;
14599 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14600 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14601 }
14602}
14603
14604static void channel_xmit_extended_xon (PLCI * plci) {
14605 DIVA_CAPI_ADAPTER * a;
14606 int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]);
14607 int i, one_requested = 0;
14608
14609 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == 0)) {
14610 return;
14611 }
14612
14613 for (i = 0; i < max_ch; i++) {
14614 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14615 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14616 (plci->Id == a->ch_flow_plci[i])) {
14617 channel_request_xon (plci, (byte)i);
14618 one_requested = 1;
14619 }
14620 }
14621
14622 if (one_requested) {
14623 channel_xmit_xon (plci);
14624 }
14625}
14626
14627/*
14628 Try to xmit next X_ON
14629 */
14630static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER * a, PLCI * plci) {
14631 int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]);
14632 int i;
14633
14634 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14635 return (0);
14636 }
14637
14638 if (a->last_flow_control_ch >= max_ch) {
14639 a->last_flow_control_ch = 1;
14640 }
14641 for (i=a->last_flow_control_ch; i < max_ch; i++) {
14642 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14643 (plci->Id == a->ch_flow_plci[i])) {
14644 a->last_flow_control_ch = i+1;
14645 return (i);
14646 }
14647 }
14648
14649 for (i = 1; i < a->last_flow_control_ch; i++) {
14650 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14651 (plci->Id == a->ch_flow_plci[i])) {
14652 a->last_flow_control_ch = i+1;
14653 return (i);
14654 }
14655 }
14656
14657 return (0);
14658}
14659
14660static void channel_xmit_xon (PLCI * plci) {
14661 DIVA_CAPI_ADAPTER * a = plci->adapter;
14662 byte ch;
14663
14664 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14665 return;
14666 }
14667 if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14668 return;
14669 }
14670 a->ch_flow_control[ch] &= ~N_XON_REQ;
14671 a->ch_flow_control[ch] |= N_XON_SENT;
14672
14673 plci->NL.Req = plci->nl_req = (byte)N_XON;
14674 plci->NL.ReqCh = ch;
14675 plci->NL.X = plci->NData;
14676 plci->NL.XNum = 1;
14677 plci->NData[0].P = &plci->RBuffer[0];
14678 plci->NData[0].PLength = 0;
14679
14680 plci->adapter->request(&plci->NL);
14681}
14682
14683static int channel_can_xon (PLCI * plci, byte ch) {
14684 APPL * APPLptr;
14685 DIVA_CAPI_ADAPTER * a;
14686 word NCCIcode;
14687 dword count;
14688 word Num;
14689 word i;
14690
14691 APPLptr = plci->appl;
14692 a = plci->adapter;
14693
14694 if (!APPLptr)
14695 return (0);
14696
14697 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14698
14699 /* count all buffers within the Application pool */
14700 /* belonging to the same NCCI. XON if a first is */
14701 /* used. */
14702 count = 0;
14703 Num = 0xffff;
14704 for(i=0; i<APPLptr->MaxBuffer; i++) {
14705 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14706 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14707 }
14708 if ((count > 2) || (Num == 0xffff)) {
14709 return (0);
14710 }
14711 return (1);
14712}
14713
14714
14715/*------------------------------------------------------------------*/
14716
14717static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER * a,word offset)
14718{
14719 return 1;
14720}
14721
14722
14723
14724/**********************************************************************************/
14725/* function groups the listening applications according to the CIP mask and the */
14726/* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14727/* are not multi-instance capable, so they start e.g. 30 applications what causes */
14728/* big problems on application level (one call, 30 Connect_Ind, ect). The */
14729/* function must be enabled by setting "a->group_optimization_enabled" from the */
14730/* OS specific part (per adapter). */
14731/**********************************************************************************/
14732static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci)
14733{
14734 word i,j,k,busy,group_found;
14735 dword info_mask_group[MAX_CIP_TYPES];
14736 dword cip_mask_group[MAX_CIP_TYPES];
14737 word appl_number_group_type[MAX_APPL];
14738 PLCI *auxplci;
14739
14740 set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14741
14742 if(!a->group_optimization_enabled)
14743 {
14744 dbug(1,dprintf("No group optimization"));
14745 return;
14746 }
14747
14748 dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14749
14750 for(i=0;i<MAX_CIP_TYPES;i++)
14751 {
14752 info_mask_group[i] = 0;
14753 cip_mask_group [i] = 0;
14754 }
14755 for(i=0;i<MAX_APPL;i++)
14756 {
14757 appl_number_group_type[i] = 0;
14758 }
14759 for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14760 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14761 if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled ==1) )
14762 {
14763 dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14764 return; /* allow good application unfiltered access */
14765 }
14766 }
14767 for(i=0; i<max_appl; i++) /* Build CIP Groups */
14768 {
14769 if(application[i].Id && a->CIP_Mask[i] )
14770 {
14771 for(k=0,busy=FALSE; k<a->max_plci; k++)
14772 {
14773 if(a->plci[k].Id)
14774 {
14775 auxplci = &a->plci[k];
14776 if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14777 {
14778 busy = TRUE;
14779 dbug(1,dprintf("Appl 0x%x is busy",i+1));
14780 }
14781 else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14782 {
14783 busy = TRUE;
14784 dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14785 }
14786 }
14787 }
14788
14789 for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++) /* build groups with free applications only */
14790 {
14791 if(j==MAX_CIP_TYPES) /* all groups are in use but group still not found */
14792 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14793 appl_number_group_type[i] = MAX_CIP_TYPES;
14794 group_found=TRUE;
14795 dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14796 }
14797 else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )
14798 { /* is group already present ? */
14799 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14800 group_found=TRUE;
14801 dbug(1,dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
14802 }
14803 else if(!info_mask_group[j])
14804 { /* establish a new group */
14805 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14806 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14807 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
14808 group_found=TRUE;
14809 dbug(1,dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
14810 }
14811 }
14812 }
14813 }
14814
14815 for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14816 {
14817 if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14818 {
14819 if(appl_number_group_type[i] == MAX_CIP_TYPES)
14820 {
14821 dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14822 }
14823 else
14824 {
14825 dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14826 for(j=i+1; j<max_appl; j++) /* search other group members and mark them as busy */
14827 {
14828 if(appl_number_group_type[i] == appl_number_group_type[j])
14829 {
14830 dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14831 clear_group_ind_mask_bit (plci, j); /* disable call on other group members */
14832 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14833 }
14834 }
14835 }
14836 }
14837 else /* application should not get a call */
14838 {
14839 clear_group_ind_mask_bit (plci, i);
14840 }
14841 }
14842
14843}
14844
14845
14846
14847/* OS notifies the driver about a application Capi_Register */
14848word CapiRegister(word id)
14849{
14850 word i,j,appls_found;
14851
14852 PLCI *plci;
14853 DIVA_CAPI_ADAPTER *a;
14854
14855 for(i=0,appls_found=0; i<max_appl; i++)
14856 {
14857 if( application[i].Id && (application[i].Id!=id) )
14858 {
14859 appls_found++; /* an application has been found */
14860 }
14861 }
14862
14863 if(appls_found) return TRUE;
14864 for(i=0; i<max_adapter; i++) /* scan all adapters... */
14865 {
14866 a = &adapter[i];
14867 if(a->request)
14868 {
14869 if(a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14870 {
14871 if(!appls_found) /* first application does a capi register */
14872 {
14873 if((j=get_plci(a))) /* activate L1 of all adapters */
14874 {
14875 plci = &a->plci[j-1];
14876 plci->command = 0;
14877 add_p(plci,OAD,"\x01\xfd");
14878 add_p(plci,CAI,"\x01\x80");
14879 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14880 add_p(plci,SHIFT|6,NULL);
14881 add_p(plci,SIN,"\x02\x00\x00");
14882 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14883 sig_req(plci,ASSIGN,DSIG_ID);
14884 add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14885 sig_req(plci,SIG_CTRL,0);
14886 send_req(plci);
14887 }
14888 }
14889 }
14890 }
14891 }
14892 return FALSE;
14893}
14894
14895/*------------------------------------------------------------------*/
14896
14897/* Functions for virtual Switching e.g. Transfer by join, Conference */
14898
14899static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14900{
14901 word i;
14902 /* Format of vswitch_t:
14903 0 byte length
14904 1 byte VSWITCHIE
14905 2 byte VSWITCH_REQ/VSWITCH_IND
14906 3 byte reserved
14907 4 word VSwitchcommand
14908 6 word returnerror
14909 8... Params
14910 */
14911 if(!plci ||
14912 !plci->appl ||
14913 !plci->State ||
14914 plci->Sig.Ind==NCR_FACILITY
14915 )
14916 return;
14917
14918 for(i=0;i<MAX_MULTI_IE;i++)
14919 {
14920 if(!parms[i][0]) continue;
14921 if(parms[i][0]<7)
14922 {
14923 parms[i][0]=0; /* kill it */
14924 continue;
14925 }
14926 dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14927 switch(parms[i][4])
14928 {
14929 case VSJOIN:
14930 if(!plci->relatedPTYPLCI ||
14931 (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14932 { /* Error */
14933 break;
14934 }
14935 /* remember all necessary informations */
14936 if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14937 {
14938 break;
14939 }
14940 if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14941 { /* first indication after ECT-Request on Consultation Call */
14942 plci->vswitchstate=parms[i][9];
14943 parms[i][9]=2; /* State */
14944 /* now ask first Call to join */
14945 }
14946 else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14947 { /* Answer of VSWITCH_REQ from first Call */
14948 plci->vswitchstate=parms[i][9];
14949 /* tell consultation call to join
14950 and the protocol capabilities of the first call */
14951 }
14952 else
14953 { /* Error */
14954 break;
14955 }
14956 plci->vsprot=parms[i][10]; /* protocol */
14957 plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14958 /* send join request to related PLCI */
14959 parms[i][1]=VSWITCHIE;
14960 parms[i][2]=VSWITCH_REQ;
14961
14962 plci->relatedPTYPLCI->command = 0;
14963 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14964 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14965 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14966 send_req(plci->relatedPTYPLCI);
14967 break;
14968 case VSTRANSPORT:
14969 default:
14970 if(plci->relatedPTYPLCI &&
14971 plci->vswitchstate==3 &&
14972 plci->relatedPTYPLCI->vswitchstate==3)
14973 {
14974 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14975 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14976 send_req(plci->relatedPTYPLCI);
14977 }
14978 break;
14979 }
14980 parms[i][0]=0; /* kill it */
14981 }
14982}
14983
14984
14985/*------------------------------------------------------------------*/
14986
14987static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic) {
14988 ENTITY e;
14989 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
14990
14991 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14992 return (-1);
14993 }
14994
14995 pReq->xdi_dma_descriptor_operation.Req = 0;
14996 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14997
14998 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14999 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
15000 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15001 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15002
15003 e.user[0] = plci->adapter->Id - 1;
15004 plci->adapter->request((ENTITY*)pReq);
15005
15006 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15007 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15008 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15009 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15010 dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15011 plci->adapter->Id,
15012 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15013 *dma_magic));
15014 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15015 } else {
15016 dbug(1,dprintf("dma_alloc failed"));
15017 return (-1);
15018 }
15019}
15020
15021static void diva_free_dma_descriptor (PLCI *plci, int nr) {
15022 ENTITY e;
15023 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15024
15025 if (nr < 0) {
15026 return;
15027 }
15028
15029 pReq->xdi_dma_descriptor_operation.Req = 0;
15030 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15031
15032 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15033 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15034 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15035 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15036
15037 e.user[0] = plci->adapter->Id - 1;
15038 plci->adapter->request((ENTITY*)pReq);
15039
15040 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15041 dbug(1,dprintf("dma_free(%d)", nr));
15042 } else {
15043 dbug(1,dprintf("dma_free failed (%d)", nr));
15044 }
15045}
15046
15047/*------------------------------------------------------------------*/
diff --git a/drivers/isdn/hardware/eicon/mi_pc.h b/drivers/isdn/hardware/eicon/mi_pc.h
new file mode 100644
index 000000000000..a861dac1f784
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/mi_pc.h
@@ -0,0 +1,204 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26/*----------------------------------------------------------------------------
27// MAESTRA ISA PnP */
28#define BRI_MEMORY_BASE 0x1f700000
29#define BRI_MEMORY_SIZE 0x00100000 /* 1MB on the BRI */
30#define BRI_SHARED_RAM_SIZE 0x00010000 /* 64k shared RAM */
31#define BRI_RAY_TAYLOR_DSP_CODE_SIZE 0x00020000 /* max 128k DSP-Code (Ray Taylor's code) */
32#define BRI_ORG_MAX_DSP_CODE_SIZE 0x00050000 /* max 320k DSP-Code (Telindus) */
33#define BRI_V90D_MAX_DSP_CODE_SIZE 0x00060000 /* max 384k DSP-Code if V.90D included */
34#define BRI_CACHED_ADDR(x) (((x) & 0x1fffffffL) | 0x80000000L)
35#define BRI_UNCACHED_ADDR(x) (((x) & 0x1fffffffL) | 0xa0000000L)
36#define ADDR 4
37#define ADDRH 6
38#define DATA 0
39#define RESET 7
40#define DEFAULT_ADDRESS 0x240
41#define DEFAULT_IRQ 3
42#define M_PCI_ADDR 0x04 /* MAESTRA BRI PCI */
43#define M_PCI_ADDRH 0x0c /* MAESTRA BRI PCI */
44#define M_PCI_DATA 0x00 /* MAESTRA BRI PCI */
45#define M_PCI_RESET 0x10 /* MAESTRA BRI PCI */
46/*----------------------------------------------------------------------------
47// MAESTRA PRI PCI */
48#define MP_IRQ_RESET 0xc18 /* offset of isr in the CONFIG memory bar */
49#define MP_IRQ_RESET_VAL 0xfe /* value to clear an interrupt */
50#define MP_MEMORY_SIZE 0x00400000 /* 4MB on standard PRI */
51#define MP2_MEMORY_SIZE 0x00800000 /* 8MB on PRI Rev. 2 */
52#define MP_SHARED_RAM_OFFSET 0x00001000 /* offset of shared RAM base in the DRAM memory bar */
53#define MP_SHARED_RAM_SIZE 0x00010000 /* 64k shared RAM */
54#define MP_PROTOCOL_OFFSET (MP_SHARED_RAM_OFFSET + MP_SHARED_RAM_SIZE)
55#define MP_RAY_TAYLOR_DSP_CODE_SIZE 0x00040000 /* max 256k DSP-Code (Ray Taylor's code) */
56#define MP_ORG_MAX_DSP_CODE_SIZE 0x00060000 /* max 384k DSP-Code (Telindus) */
57#define MP_V90D_MAX_DSP_CODE_SIZE 0x00070000 /* max 448k DSP-Code if V.90D included) */
58#define MP_VOIP_MAX_DSP_CODE_SIZE 0x00090000 /* max 576k DSP-Code if voice over IP included */
59#define MP_CACHED_ADDR(x) (((x) & 0x1fffffffL) | 0x80000000L)
60#define MP_UNCACHED_ADDR(x) (((x) & 0x1fffffffL) | 0xa0000000L)
61#define MP_RESET 0x20 /* offset of RESET register in the DEVICES memory bar */
62/* RESET register bits */
63#define _MP_S2M_RESET 0x10 /* active lo */
64#define _MP_LED2 0x08 /* 1 = on */
65#define _MP_LED1 0x04 /* 1 = on */
66#define _MP_DSP_RESET 0x02 /* active lo */
67#define _MP_RISC_RESET 0x81 /* active hi, bit 7 for compatibility with old boards */
68/* CPU exception context structure in MP shared ram after trap */
69typedef struct mp_xcptcontext_s MP_XCPTC;
70struct mp_xcptcontext_s {
71 dword sr;
72 dword cr;
73 dword epc;
74 dword vaddr;
75 dword regs[32];
76 dword mdlo;
77 dword mdhi;
78 dword reseverd;
79 dword xclass;
80};
81/* boot interface structure for PRI */
82struct mp_load {
83 dword volatile cmd;
84 dword volatile addr;
85 dword volatile len;
86 dword volatile err;
87 dword volatile live;
88 dword volatile res1[0x1b];
89 dword volatile TrapId; /* has value 0x999999XX on a CPU trap */
90 dword volatile res2[0x03];
91 MP_XCPTC volatile xcpt; /* contains register dump */
92 dword volatile rest[((0x1020>>2)-6) - 0x1b - 1 - 0x03 - (sizeof(MP_XCPTC)>>2)];
93 dword volatile signature;
94 dword data[60000]; /* real interface description */
95};
96/*----------------------------------------------------------------------------*/
97/* SERVER 4BRI (Quattro PCI) */
98#define MQ_BOARD_REG_OFFSET 0x800000 /* PC relative On board registers offset */
99#define MQ_BREG_RISC 0x1200 /* RISC Reset ect */
100#define MQ_RISC_COLD_RESET_MASK 0x0001 /* RISC Cold reset */
101#define MQ_RISC_WARM_RESET_MASK 0x0002 /* RISC Warm reset */
102#define MQ_BREG_IRQ_TEST 0x0608 /* Interrupt request, no CPU interaction */
103#define MQ_IRQ_REQ_ON 0x1
104#define MQ_IRQ_REQ_OFF 0x0
105#define MQ_BOARD_DSP_OFFSET 0xa00000 /* PC relative On board DSP regs offset */
106#define MQ_DSP1_ADDR_OFFSET 0x0008 /* Addr register offset DSP 1 subboard 1 */
107#define MQ_DSP2_ADDR_OFFSET 0x0208 /* Addr register offset DSP 2 subboard 1 */
108#define MQ_DSP1_DATA_OFFSET 0x0000 /* Data register offset DSP 1 subboard 1 */
109#define MQ_DSP2_DATA_OFFSET 0x0200 /* Data register offset DSP 2 subboard 1 */
110#define MQ_DSP_JUNK_OFFSET 0x0400 /* DSP Data/Addr regs subboard offset */
111#define MQ_ISAC_DSP_RESET 0x0028 /* ISAC and DSP reset address offset */
112#define MQ_BOARD_ISAC_DSP_RESET 0x800028 /* ISAC and DSP reset address offset */
113#define MQ_INSTANCE_COUNT 4 /* 4BRI consists of four instances */
114#define MQ_MEMORY_SIZE 0x00400000 /* 4MB on standard 4BRI */
115#define MQ_CTRL_SIZE 0x00002000 /* 8K memory mapped registers */
116#define MQ_SHARED_RAM_SIZE 0x00010000 /* 64k shared RAM */
117#define MQ_ORG_MAX_DSP_CODE_SIZE 0x00050000 /* max 320k DSP-Code (Telindus) */
118#define MQ_V90D_MAX_DSP_CODE_SIZE 0x00060000 /* max 384K DSP-Code if V.90D included */
119#define MQ_VOIP_MAX_DSP_CODE_SIZE 0x00028000 /* max 4*160k = 640K DSP-Code if voice over IP included */
120#define MQ_CACHED_ADDR(x) (((x) & 0x1fffffffL) | 0x80000000L)
121#define MQ_UNCACHED_ADDR(x) (((x) & 0x1fffffffL) | 0xa0000000L)
122/*--------------------------------------------------------------------------------------------*/
123/* Additional definitions reflecting the different address map of the SERVER 4BRI V2 */
124#define MQ2_BREG_RISC 0x0200 /* RISC Reset ect */
125#define MQ2_BREG_IRQ_TEST 0x0400 /* Interrupt request, no CPU interaction */
126#define MQ2_BOARD_DSP_OFFSET 0x800000 /* PC relative On board DSP regs offset */
127#define MQ2_DSP1_DATA_OFFSET 0x1800 /* Data register offset DSP 1 subboard 1 */
128#define MQ2_DSP1_ADDR_OFFSET 0x1808 /* Addr register offset DSP 1 subboard 1 */
129#define MQ2_DSP2_DATA_OFFSET 0x1810 /* Data register offset DSP 2 subboard 1 */
130#define MQ2_DSP2_ADDR_OFFSET 0x1818 /* Addr register offset DSP 2 subboard 1 */
131#define MQ2_DSP_JUNK_OFFSET 0x1000 /* DSP Data/Addr regs subboard offset */
132#define MQ2_ISAC_DSP_RESET 0x0000 /* ISAC and DSP reset address offset */
133#define MQ2_BOARD_ISAC_DSP_RESET 0x800000 /* ISAC and DSP reset address offset */
134#define MQ2_IPACX_CONFIG 0x0300 /* IPACX Configuration TE(0)/NT(1) */
135#define MQ2_BOARD_IPACX_CONFIG 0x800300 /* "" */
136#define MQ2_MEMORY_SIZE 0x01000000 /* 16MB code/data memory */
137#define MQ2_CTRL_SIZE 0x00008000 /* 32K memory mapped registers */
138/*----------------------------------------------------------------------------*/
139/* SERVER BRI 2M/2F as derived from 4BRI V2 */
140#define BRI2_MEMORY_SIZE 0x00800000 /* 8MB code/data memory */
141#define BRI2_PROTOCOL_MEMORY_SIZE (MQ2_MEMORY_SIZE >> 2) /* same as one 4BRI Rev.2 task */
142#define BRI2_CTRL_SIZE 0x00008000 /* 32K memory mapped registers */
143#define M_INSTANCE_COUNT 1 /* BRI consists of one instance */
144/*
145 * Some useful constants for proper initialization of the GT6401x
146 */
147#define ID_REG 0x0000 /*Pci reg-contain the Dev&Ven ID of the card*/
148#define RAS0_BASEREG 0x0010 /*Ras0 register - contain the base addr Ras0*/
149#define RAS2_BASEREG 0x0014
150#define CS_BASEREG 0x0018
151#define BOOT_BASEREG 0x001c
152#define GTREGS_BASEREG 0x0024 /*GTRegsBase reg-contain the base addr where*/
153 /*the GT64010 internal regs where mapped */
154/*
155 * GT64010 internal registers
156 */
157 /* DRAM device coding */
158#define LOW_RAS0_DREG 0x0400 /*Ras0 low decode address*/
159#define HI_RAS0_DREG 0x0404 /*Ras0 high decode address*/
160#define LOW_RAS1_DREG 0x0408 /*Ras1 low decode address*/
161#define HI_RAS1_DREG 0x040c /*Ras1 high decode address*/
162#define LOW_RAS2_DREG 0x0410 /*Ras2 low decode address*/
163#define HI_RAS2_DREG 0x0414 /*Ras2 high decode address*/
164#define LOW_RAS3_DREG 0x0418 /*Ras3 low decode address*/
165#define HI_RAS3_DREG 0x041c /*Ras3 high decode address*/
166 /* I/O CS device coding */
167#define LOW_CS0_DREG 0x0420 /* CS0* low decode register */
168#define HI_CS0_DREG 0x0424 /* CS0* high decode register */
169#define LOW_CS1_DREG 0x0428 /* CS1* low decode register */
170#define HI_CS1_DREG 0x042c /* CS1* high decode register */
171#define LOW_CS2_DREG 0x0430 /* CS2* low decode register */
172#define HI_CS2_DREG 0x0434 /* CS2* high decode register */
173#define LOW_CS3_DREG 0x0438 /* CS3* low decode register */
174#define HI_CS3_DREG 0x043c /* CS3* high decode register */
175 /* Boot PROM device coding */
176#define LOW_BOOTCS_DREG 0x0440 /* Boot CS low decode register */
177#define HI_BOOTCS_DREG 0x0444 /* Boot CS High decode register */
178 /* DRAM group coding (for CPU) */
179#define LO_RAS10_GREG 0x0008 /*Ras1..0 group low decode address*/
180#define HI_RAS10_GREG 0x0010 /*Ras1..0 group high decode address*/
181#define LO_RAS32_GREG 0x0018 /*Ras3..2 group low decode address */
182#define HI_RAS32_GREG 0x0020 /*Ras3..2 group high decode address */
183 /* I/O CS group coding for (CPU) */
184#define LO_CS20_GREG 0x0028 /* CS2..0 group low decode register */
185#define HI_CS20_GREG 0x0030 /* CS2..0 group high decode register */
186#define LO_CS3B_GREG 0x0038 /* CS3 & PROM group low decode register */
187#define HI_CS3B_GREG 0x0040 /* CS3 & PROM group high decode register */
188 /* Galileo specific PCI config. */
189#define PCI_TIMEOUT_RET 0x0c04 /* Time Out and retry register */
190#define RAS10_BANKSIZE 0x0c08 /* RAS 1..0 group PCI bank size */
191#define RAS32_BANKSIZE 0x0c0c /* RAS 3..2 group PCI bank size */
192#define CS20_BANKSIZE 0x0c10 /* CS 2..0 group PCI bank size */
193#define CS3B_BANKSIZE 0x0c14 /* CS 3 & Boot group PCI bank size */
194#define DRAM_SIZE 0x0001 /*Dram size in mega bytes*/
195#define PROM_SIZE 0x08000 /*Prom size in bytes*/
196/*--------------------------------------------------------------------------*/
197#define OFFS_DIVA_INIT_TASK_COUNT 0x68
198#define OFFS_DSP_CODE_BASE_ADDR 0x6c
199#define OFFS_XLOG_BUF_ADDR 0x70
200#define OFFS_XLOG_COUNT_ADDR 0x74
201#define OFFS_XLOG_OUT_ADDR 0x78
202#define OFFS_PROTOCOL_END_ADDR 0x7c
203#define OFFS_PROTOCOL_ID_STRING 0x80
204/*--------------------------------------------------------------------------*/
diff --git a/drivers/isdn/hardware/eicon/mntfunc.c b/drivers/isdn/hardware/eicon/mntfunc.c
new file mode 100644
index 000000000000..a564b7560031
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/mntfunc.c
@@ -0,0 +1,370 @@
1/* $Id: mntfunc.c,v 1.19.6.4 2005/01/31 12:22:20 armin Exp $
2 *
3 * Driver for Eicon DIVA Server ISDN cards.
4 * Maint module
5 *
6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 */
12
13
14#include "platform.h"
15#include "di_defs.h"
16#include "divasync.h"
17#include "debug_if.h"
18
19extern char *DRIVERRELEASE_MNT;
20
21#define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR)
22#define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG)
23
24extern void DIVA_DIDD_Read(void *, int);
25
26static dword notify_handle;
27static DESCRIPTOR DAdapter;
28static DESCRIPTOR MAdapter;
29static DESCRIPTOR MaintDescriptor =
30 { IDI_DIMAINT, 0, 0, (IDI_CALL) diva_maint_prtComp };
31
32extern int diva_os_copy_to_user(void *os_handle, void __user *dst,
33 const void *src, int length);
34extern int diva_os_copy_from_user(void *os_handle, void *dst,
35 const void __user *src, int length);
36
37static void no_printf(unsigned char *x, ...)
38{
39 /* dummy debug function */
40}
41
42#include "debuglib.c"
43
44/*
45 * DIDD callback function
46 */
47static void *didd_callback(void *context, DESCRIPTOR * adapter,
48 int removal)
49{
50 if (adapter->type == IDI_DADAPTER) {
51 DBG_ERR(("cb: Change in DAdapter ? Oops ?."));
52 } else if (adapter->type == IDI_DIMAINT) {
53 if (removal) {
54 DbgDeregister();
55 memset(&MAdapter, 0, sizeof(MAdapter));
56 dprintf = no_printf;
57 } else {
58 memcpy(&MAdapter, adapter, sizeof(MAdapter));
59 dprintf = (DIVA_DI_PRINTF) MAdapter.request;
60 DbgRegister("MAINT", DRIVERRELEASE_MNT, DBG_DEFAULT);
61 }
62 } else if ((adapter->type > 0) && (adapter->type < 16)) {
63 if (removal) {
64 diva_mnt_remove_xdi_adapter(adapter);
65 } else {
66 diva_mnt_add_xdi_adapter(adapter);
67 }
68 }
69 return (NULL);
70}
71
72/*
73 * connect to didd
74 */
75static int DIVA_INIT_FUNCTION connect_didd(void)
76{
77 int x = 0;
78 int dadapter = 0;
79 IDI_SYNC_REQ req;
80 DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
81
82 DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
83
84 for (x = 0; x < MAX_DESCRIPTORS; x++) {
85 if (DIDD_Table[x].type == IDI_DADAPTER) { /* DADAPTER found */
86 dadapter = 1;
87 memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
88 req.didd_notify.e.Req = 0;
89 req.didd_notify.e.Rc =
90 IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
91 req.didd_notify.info.callback = (void *)didd_callback;
92 req.didd_notify.info.context = NULL;
93 DAdapter.request((ENTITY *) & req);
94 if (req.didd_notify.e.Rc != 0xff)
95 return (0);
96 notify_handle = req.didd_notify.info.handle;
97 /* Register MAINT (me) */
98 req.didd_add_adapter.e.Req = 0;
99 req.didd_add_adapter.e.Rc =
100 IDI_SYNC_REQ_DIDD_ADD_ADAPTER;
101 req.didd_add_adapter.info.descriptor =
102 (void *) &MaintDescriptor;
103 DAdapter.request((ENTITY *) & req);
104 if (req.didd_add_adapter.e.Rc != 0xff)
105 return (0);
106 } else if ((DIDD_Table[x].type > 0)
107 && (DIDD_Table[x].type < 16)) {
108 diva_mnt_add_xdi_adapter(&DIDD_Table[x]);
109 }
110 }
111 return (dadapter);
112}
113
114/*
115 * disconnect from didd
116 */
117static void DIVA_EXIT_FUNCTION disconnect_didd(void)
118{
119 IDI_SYNC_REQ req;
120
121 req.didd_notify.e.Req = 0;
122 req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
123 req.didd_notify.info.handle = notify_handle;
124 DAdapter.request((ENTITY *) & req);
125
126 req.didd_remove_adapter.e.Req = 0;
127 req.didd_remove_adapter.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER;
128 req.didd_remove_adapter.info.p_request =
129 (IDI_CALL) MaintDescriptor.request;
130 DAdapter.request((ENTITY *) & req);
131}
132
133/*
134 * read/write maint
135 */
136int maint_read_write(void __user *buf, int count)
137{
138 byte data[128];
139 dword cmd, id, mask;
140 int ret = 0;
141
142 if (count < (3 * sizeof(dword)))
143 return (-EFAULT);
144
145 if (diva_os_copy_from_user(NULL, (void *) &data[0],
146 buf, 3 * sizeof(dword))) {
147 return (-EFAULT);
148 }
149
150 cmd = *(dword *) & data[0]; /* command */
151 id = *(dword *) & data[4]; /* driver id */
152 mask = *(dword *) & data[8]; /* mask or size */
153
154 switch (cmd) {
155 case DITRACE_CMD_GET_DRIVER_INFO:
156 if ((ret = diva_get_driver_info(id, data, sizeof(data))) > 0) {
157 if ((count < ret) || diva_os_copy_to_user
158 (NULL, buf, (void *) &data[0], ret))
159 ret = -EFAULT;
160 } else {
161 ret = -EINVAL;
162 }
163 break;
164
165 case DITRACE_READ_DRIVER_DBG_MASK:
166 if ((ret = diva_get_driver_dbg_mask(id, (byte *) data)) > 0) {
167 if ((count < ret) || diva_os_copy_to_user
168 (NULL, buf, (void *) &data[0], ret))
169 ret = -EFAULT;
170 } else {
171 ret = -ENODEV;
172 }
173 break;
174
175 case DITRACE_WRITE_DRIVER_DBG_MASK:
176 if ((ret = diva_set_driver_dbg_mask(id, mask)) <= 0) {
177 ret = -ENODEV;
178 }
179 break;
180
181 /*
182 Filter commands will ignore the ID due to fact that filtering affects
183 the B- channel and Audio Tap trace levels only. Also MAINT driver will
184 select the right trace ID by itself
185 */
186 case DITRACE_WRITE_SELECTIVE_TRACE_FILTER:
187 if (!mask) {
188 ret = diva_set_trace_filter (1, "*");
189 } else if (mask < sizeof(data)) {
190 if (diva_os_copy_from_user(NULL, data, (char __user *)buf+12, mask)) {
191 ret = -EFAULT;
192 } else {
193 ret = diva_set_trace_filter ((int)mask, data);
194 }
195 } else {
196 ret = -EINVAL;
197 }
198 break;
199
200 case DITRACE_READ_SELECTIVE_TRACE_FILTER:
201 if ((ret = diva_get_trace_filter (sizeof(data), data)) > 0) {
202 if (diva_os_copy_to_user (NULL, buf, data, ret))
203 ret = -EFAULT;
204 } else {
205 ret = -ENODEV;
206 }
207 break;
208
209 case DITRACE_READ_TRACE_ENTRY:{
210 diva_os_spin_lock_magic_t old_irql;
211 word size;
212 diva_dbg_entry_head_t *pmsg;
213 byte *pbuf;
214
215 if (!(pbuf = diva_os_malloc(0, mask))) {
216 return (-ENOMEM);
217 }
218
219 for(;;) {
220 if (!(pmsg =
221 diva_maint_get_message(&size, &old_irql))) {
222 break;
223 }
224 if (size > mask) {
225 diva_maint_ack_message(0, &old_irql);
226 ret = -EINVAL;
227 break;
228 }
229 ret = size;
230 memcpy(pbuf, pmsg, size);
231 diva_maint_ack_message(1, &old_irql);
232 if ((count < size) ||
233 diva_os_copy_to_user (NULL, buf, (void *) pbuf, size))
234 ret = -EFAULT;
235 break;
236 }
237 diva_os_free(0, pbuf);
238 }
239 break;
240
241 case DITRACE_READ_TRACE_ENTRYS:{
242 diva_os_spin_lock_magic_t old_irql;
243 word size;
244 diva_dbg_entry_head_t *pmsg;
245 byte *pbuf = NULL;
246 int written = 0;
247
248 if (mask < 4096) {
249 ret = -EINVAL;
250 break;
251 }
252 if (!(pbuf = diva_os_malloc(0, mask))) {
253 return (-ENOMEM);
254 }
255
256 for (;;) {
257 if (!(pmsg =
258 diva_maint_get_message(&size, &old_irql))) {
259 break;
260 }
261 if ((size + 8) > mask) {
262 diva_maint_ack_message(0, &old_irql);
263 break;
264 }
265 /*
266 Write entry length
267 */
268 pbuf[written++] = (byte) size;
269 pbuf[written++] = (byte) (size >> 8);
270 pbuf[written++] = 0;
271 pbuf[written++] = 0;
272 /*
273 Write message
274 */
275 memcpy(&pbuf[written], pmsg, size);
276 diva_maint_ack_message(1, &old_irql);
277 written += size;
278 mask -= (size + 4);
279 }
280 pbuf[written++] = 0;
281 pbuf[written++] = 0;
282 pbuf[written++] = 0;
283 pbuf[written++] = 0;
284
285 if ((count < written) || diva_os_copy_to_user(NULL, buf, (void *) pbuf, written)) {
286 ret = -EFAULT;
287 } else {
288 ret = written;
289 }
290 diva_os_free(0, pbuf);
291 }
292 break;
293
294 default:
295 ret = -EINVAL;
296 }
297 return (ret);
298}
299
300/*
301 * init
302 */
303int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer,
304 unsigned long diva_dbg_mem)
305{
306 if (*buffer_length < 64) {
307 *buffer_length = 64;
308 }
309 if (*buffer_length > 512) {
310 *buffer_length = 512;
311 }
312 *buffer_length *= 1024;
313
314 if (diva_dbg_mem) {
315 *buffer = (void *) diva_dbg_mem;
316 } else {
317 while ((*buffer_length >= (64 * 1024))
318 &&
319 (!(*buffer = diva_os_malloc (0, *buffer_length)))) {
320 *buffer_length -= 1024;
321 }
322
323 if (!*buffer) {
324 DBG_ERR(("init: Can not alloc trace buffer"));
325 return (0);
326 }
327 }
328
329 if (diva_maint_init(*buffer, *buffer_length, (diva_dbg_mem == 0))) {
330 if (!diva_dbg_mem) {
331 diva_os_free (0, *buffer);
332 }
333 DBG_ERR(("init: maint init failed"));
334 return (0);
335 }
336
337 if (!connect_didd()) {
338 DBG_ERR(("init: failed to connect to DIDD."));
339 diva_maint_finit();
340 if (!diva_dbg_mem) {
341 diva_os_free (0, *buffer);
342 }
343 return (0);
344 }
345 return (1);
346}
347
348/*
349 * exit
350 */
351void DIVA_EXIT_FUNCTION mntfunc_finit(void)
352{
353 void *buffer;
354 int i = 100;
355
356 DbgDeregister();
357
358 while (diva_mnt_shutdown_xdi_adapters() && i--) {
359 diva_os_sleep(10);
360 }
361
362 disconnect_didd();
363
364 if ((buffer = diva_maint_finit())) {
365 diva_os_free (0, buffer);
366 }
367
368 memset(&MAdapter, 0, sizeof(MAdapter));
369 dprintf = no_printf;
370}
diff --git a/drivers/isdn/hardware/eicon/os_4bri.c b/drivers/isdn/hardware/eicon/os_4bri.c
new file mode 100644
index 000000000000..cccfabc1117d
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/os_4bri.c
@@ -0,0 +1,1131 @@
1/* $Id: os_4bri.c,v 1.28.4.4 2005/02/11 19:40:25 armin Exp $ */
2
3#include "platform.h"
4#include "debuglib.h"
5#include "cardtype.h"
6#include "pc.h"
7#include "pr_pc.h"
8#include "di_defs.h"
9#include "dsp_defs.h"
10#include "di.h"
11#include "io.h"
12
13#include "xdi_msg.h"
14#include "xdi_adapter.h"
15#include "os_4bri.h"
16#include "diva_pci.h"
17#include "mi_pc.h"
18#include "dsrv4bri.h"
19
20static void *diva_xdiLoadFileFile = NULL;
21static dword diva_xdiLoadFileLength = 0;
22
23/*
24** IMPORTS
25*/
26extern void prepare_qBri_functions(PISDN_ADAPTER IoAdapter);
27extern void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter);
28extern void diva_xdi_display_adapter_features(int card);
29extern void diva_add_slave_adapter(diva_os_xdi_adapter_t * a);
30
31extern int qBri_FPGA_download(PISDN_ADAPTER IoAdapter);
32extern void start_qBri_hardware(PISDN_ADAPTER IoAdapter);
33
34extern int diva_card_read_xlog(diva_os_xdi_adapter_t * a);
35
36/*
37** LOCALS
38*/
39static unsigned long _4bri_bar_length[4] = {
40 0x100,
41 0x100, /* I/O */
42 MQ_MEMORY_SIZE,
43 0x2000
44};
45static unsigned long _4bri_v2_bar_length[4] = {
46 0x100,
47 0x100, /* I/O */
48 MQ2_MEMORY_SIZE,
49 0x10000
50};
51static unsigned long _4bri_v2_bri_bar_length[4] = {
52 0x100,
53 0x100, /* I/O */
54 BRI2_MEMORY_SIZE,
55 0x10000
56};
57
58
59static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t * a);
60static int _4bri_get_serial_number(diva_os_xdi_adapter_t * a);
61static int diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
62 diva_xdi_um_cfg_cmd_t * cmd,
63 int length);
64static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t * a);
65static int diva_4bri_write_fpga_image(diva_os_xdi_adapter_t * a,
66 byte * data, dword length);
67static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter);
68static int diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
69 dword address,
70 const byte * data,
71 dword length, dword limit);
72static int diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
73 dword start_address, dword features);
74static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter);
75static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t * a);
76
77static int _4bri_is_rev_2_card(int card_ordinal)
78{
79 switch (card_ordinal) {
80 case CARDTYPE_DIVASRV_Q_8M_V2_PCI:
81 case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI:
82 case CARDTYPE_DIVASRV_B_2M_V2_PCI:
83 case CARDTYPE_DIVASRV_B_2F_PCI:
84 case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
85 return (1);
86 }
87 return (0);
88}
89
90static int _4bri_is_rev_2_bri_card(int card_ordinal)
91{
92 switch (card_ordinal) {
93 case CARDTYPE_DIVASRV_B_2M_V2_PCI:
94 case CARDTYPE_DIVASRV_B_2F_PCI:
95 case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
96 return (1);
97 }
98 return (0);
99}
100
101static void diva_4bri_set_addresses(diva_os_xdi_adapter_t *a)
102{
103 dword offset = a->resources.pci.qoffset;
104 dword c_offset = offset * a->xdi_adapter.ControllerNumber;
105
106 a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 2;
107 a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 2;
108 a->resources.pci.mem_type_id[MEM_TYPE_CONTROL] = 2;
109 a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 0;
110 a->resources.pci.mem_type_id[MEM_TYPE_CTLREG] = 3;
111 a->resources.pci.mem_type_id[MEM_TYPE_PROM] = 0;
112
113 /*
114 Set up hardware related pointers
115 */
116 a->xdi_adapter.Address = a->resources.pci.addr[2]; /* BAR2 SDRAM */
117 a->xdi_adapter.Address += c_offset;
118
119 a->xdi_adapter.Control = a->resources.pci.addr[2]; /* BAR2 SDRAM */
120
121 a->xdi_adapter.ram = a->resources.pci.addr[2]; /* BAR2 SDRAM */
122 a->xdi_adapter.ram += c_offset + (offset - MQ_SHARED_RAM_SIZE);
123
124 a->xdi_adapter.reset = a->resources.pci.addr[0]; /* BAR0 CONFIG */
125 /*
126 ctlReg contains the register address for the MIPS CPU reset control
127 */
128 a->xdi_adapter.ctlReg = a->resources.pci.addr[3]; /* BAR3 CNTRL */
129 /*
130 prom contains the register address for FPGA and EEPROM programming
131 */
132 a->xdi_adapter.prom = &a->xdi_adapter.reset[0x6E];
133}
134
135/*
136** BAR0 - MEM - 0x100 - CONFIG MEM
137** BAR1 - I/O - 0x100 - UNUSED
138** BAR2 - MEM - MQ_MEMORY_SIZE (MQ2_MEMORY_SIZE on Rev.2) - SDRAM
139** BAR3 - MEM - 0x2000 (0x10000 on Rev.2) - CNTRL
140**
141** Called by master adapter, that will initialize and add slave adapters
142*/
143int diva_4bri_init_card(diva_os_xdi_adapter_t * a)
144{
145 int bar, i;
146 byte __iomem *p;
147 PADAPTER_LIST_ENTRY quadro_list;
148 diva_os_xdi_adapter_t *diva_current;
149 diva_os_xdi_adapter_t *adapter_list[4];
150 PISDN_ADAPTER Slave;
151 unsigned long bar_length[sizeof(_4bri_bar_length) /
152 sizeof(_4bri_bar_length[0])];
153 int v2 = _4bri_is_rev_2_card(a->CardOrdinal);
154 int tasks = _4bri_is_rev_2_bri_card(a->CardOrdinal) ? 1 : MQ_INSTANCE_COUNT;
155 int factor = (tasks == 1) ? 1 : 2;
156
157 if (v2) {
158 if (_4bri_is_rev_2_bri_card(a->CardOrdinal)) {
159 memcpy(bar_length, _4bri_v2_bri_bar_length,
160 sizeof(bar_length));
161 } else {
162 memcpy(bar_length, _4bri_v2_bar_length,
163 sizeof(bar_length));
164 }
165 } else {
166 memcpy(bar_length, _4bri_bar_length, sizeof(bar_length));
167 }
168 DBG_TRC(("SDRAM_LENGTH=%08x, tasks=%d, factor=%d",
169 bar_length[2], tasks, factor))
170
171 /*
172 Get Serial Number
173 The serial number of 4BRI is accessible in accordance with PCI spec
174 via command register located in configuration space, also we do not
175 have to map any BAR before we can access it
176 */
177 if (!_4bri_get_serial_number(a)) {
178 DBG_ERR(("A: 4BRI can't get Serial Number"))
179 diva_4bri_cleanup_adapter(a);
180 return (-1);
181 }
182
183 /*
184 Set properties
185 */
186 a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
187 DBG_LOG(("Load %s, SN:%ld, bus:%02x, func:%02x",
188 a->xdi_adapter.Properties.Name,
189 a->xdi_adapter.serialNo,
190 a->resources.pci.bus, a->resources.pci.func))
191
192 /*
193 First initialization step: get and check hardware resoures.
194 Do not map resources and do not access card at this step
195 */
196 for (bar = 0; bar < 4; bar++) {
197 a->resources.pci.bar[bar] =
198 divasa_get_pci_bar(a->resources.pci.bus,
199 a->resources.pci.func, bar,
200 a->resources.pci.hdev);
201 if (!a->resources.pci.bar[bar]
202 || (a->resources.pci.bar[bar] == 0xFFFFFFF0)) {
203 DBG_ERR(
204 ("A: invalid bar[%d]=%08x", bar,
205 a->resources.pci.bar[bar]))
206 return (-1);
207 }
208 }
209 a->resources.pci.irq =
210 (byte) divasa_get_pci_irq(a->resources.pci.bus,
211 a->resources.pci.func,
212 a->resources.pci.hdev);
213 if (!a->resources.pci.irq) {
214 DBG_ERR(("A: invalid irq"));
215 return (-1);
216 }
217
218 a->xdi_adapter.sdram_bar = a->resources.pci.bar[2];
219
220 /*
221 Map all MEMORY BAR's
222 */
223 for (bar = 0; bar < 4; bar++) {
224 if (bar != 1) { /* ignore I/O */
225 a->resources.pci.addr[bar] =
226 divasa_remap_pci_bar(a, bar, a->resources.pci.bar[bar],
227 bar_length[bar]);
228 if (!a->resources.pci.addr[bar]) {
229 DBG_ERR(("A: 4BRI: can't map bar[%d]", bar))
230 diva_4bri_cleanup_adapter(a);
231 return (-1);
232 }
233 }
234 }
235
236 /*
237 Register I/O port
238 */
239 sprintf(&a->port_name[0], "DIVA 4BRI %ld", (long) a->xdi_adapter.serialNo);
240
241 if (diva_os_register_io_port(a, 1, a->resources.pci.bar[1],
242 bar_length[1], &a->port_name[0], 1)) {
243 DBG_ERR(("A: 4BRI: can't register bar[1]"))
244 diva_4bri_cleanup_adapter(a);
245 return (-1);
246 }
247
248 a->resources.pci.addr[1] =
249 (void *) (unsigned long) a->resources.pci.bar[1];
250
251 /*
252 Set cleanup pointer for base adapter only, so slave adapter
253 will be unable to get cleanup
254 */
255 a->interface.cleanup_adapter_proc = diva_4bri_cleanup_adapter;
256
257 /*
258 Create slave adapters
259 */
260 if (tasks > 1) {
261 if (!(a->slave_adapters[0] =
262 (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
263 {
264 diva_4bri_cleanup_adapter(a);
265 return (-1);
266 }
267 if (!(a->slave_adapters[1] =
268 (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
269 {
270 diva_os_free(0, a->slave_adapters[0]);
271 a->slave_adapters[0] = NULL;
272 diva_4bri_cleanup_adapter(a);
273 return (-1);
274 }
275 if (!(a->slave_adapters[2] =
276 (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
277 {
278 diva_os_free(0, a->slave_adapters[0]);
279 diva_os_free(0, a->slave_adapters[1]);
280 a->slave_adapters[0] = NULL;
281 a->slave_adapters[1] = NULL;
282 diva_4bri_cleanup_adapter(a);
283 return (-1);
284 }
285 memset(a->slave_adapters[0], 0x00, sizeof(*a));
286 memset(a->slave_adapters[1], 0x00, sizeof(*a));
287 memset(a->slave_adapters[2], 0x00, sizeof(*a));
288 }
289
290 adapter_list[0] = a;
291 adapter_list[1] = a->slave_adapters[0];
292 adapter_list[2] = a->slave_adapters[1];
293 adapter_list[3] = a->slave_adapters[2];
294
295 /*
296 Allocate slave list
297 */
298 quadro_list =
299 (PADAPTER_LIST_ENTRY) diva_os_malloc(0, sizeof(*quadro_list));
300 if (!(a->slave_list = quadro_list)) {
301 for (i = 0; i < (tasks - 1); i++) {
302 diva_os_free(0, a->slave_adapters[i]);
303 a->slave_adapters[i] = NULL;
304 }
305 diva_4bri_cleanup_adapter(a);
306 return (-1);
307 }
308 memset(quadro_list, 0x00, sizeof(*quadro_list));
309
310 /*
311 Set interfaces
312 */
313 a->xdi_adapter.QuadroList = quadro_list;
314 for (i = 0; i < tasks; i++) {
315 adapter_list[i]->xdi_adapter.ControllerNumber = i;
316 adapter_list[i]->xdi_adapter.tasks = tasks;
317 quadro_list->QuadroAdapter[i] =
318 &adapter_list[i]->xdi_adapter;
319 }
320
321 for (i = 0; i < tasks; i++) {
322 diva_current = adapter_list[i];
323
324 diva_current->dsp_mask = 0x00000003;
325
326 diva_current->xdi_adapter.a.io =
327 &diva_current->xdi_adapter;
328 diva_current->xdi_adapter.DIRequest = request;
329 diva_current->interface.cmd_proc = diva_4bri_cmd_card_proc;
330 diva_current->xdi_adapter.Properties =
331 CardProperties[a->CardOrdinal];
332 diva_current->CardOrdinal = a->CardOrdinal;
333
334 diva_current->xdi_adapter.Channels =
335 CardProperties[a->CardOrdinal].Channels;
336 diva_current->xdi_adapter.e_max =
337 CardProperties[a->CardOrdinal].E_info;
338 diva_current->xdi_adapter.e_tbl =
339 diva_os_malloc(0,
340 diva_current->xdi_adapter.e_max *
341 sizeof(E_INFO));
342
343 if (!diva_current->xdi_adapter.e_tbl) {
344 diva_4bri_cleanup_slave_adapters(a);
345 diva_4bri_cleanup_adapter(a);
346 for (i = 1; i < (tasks - 1); i++) {
347 diva_os_free(0, adapter_list[i]);
348 }
349 return (-1);
350 }
351 memset(diva_current->xdi_adapter.e_tbl, 0x00,
352 diva_current->xdi_adapter.e_max * sizeof(E_INFO));
353
354 if (diva_os_initialize_spin_lock(&diva_current->xdi_adapter.isr_spin_lock, "isr")) {
355 diva_4bri_cleanup_slave_adapters(a);
356 diva_4bri_cleanup_adapter(a);
357 for (i = 1; i < (tasks - 1); i++) {
358 diva_os_free(0, adapter_list[i]);
359 }
360 return (-1);
361 }
362 if (diva_os_initialize_spin_lock(&diva_current->xdi_adapter.data_spin_lock, "data")) {
363 diva_4bri_cleanup_slave_adapters(a);
364 diva_4bri_cleanup_adapter(a);
365 for (i = 1; i < (tasks - 1); i++) {
366 diva_os_free(0, adapter_list[i]);
367 }
368 return (-1);
369 }
370
371 strcpy(diva_current->xdi_adapter.req_soft_isr. dpc_thread_name, "kdivas4brid");
372
373 if (diva_os_initialize_soft_isr (&diva_current->xdi_adapter.req_soft_isr, DIDpcRoutine,
374 &diva_current->xdi_adapter)) {
375 diva_4bri_cleanup_slave_adapters(a);
376 diva_4bri_cleanup_adapter(a);
377 for (i = 1; i < (tasks - 1); i++) {
378 diva_os_free(0, adapter_list[i]);
379 }
380 return (-1);
381 }
382
383 /*
384 Do not initialize second DPC - only one thread will be created
385 */
386 diva_current->xdi_adapter.isr_soft_isr.object =
387 diva_current->xdi_adapter.req_soft_isr.object;
388 }
389
390 if (v2) {
391 prepare_qBri2_functions(&a->xdi_adapter);
392 } else {
393 prepare_qBri_functions(&a->xdi_adapter);
394 }
395
396 for (i = 0; i < tasks; i++) {
397 diva_current = adapter_list[i];
398 if (i)
399 memcpy(&diva_current->resources, &a->resources, sizeof(divas_card_resources_t));
400 diva_current->resources.pci.qoffset = (a->xdi_adapter.MemorySize >> factor);
401 }
402
403 /*
404 Set up hardware related pointers
405 */
406 a->xdi_adapter.cfg = (void *) (unsigned long) a->resources.pci.bar[0]; /* BAR0 CONFIG */
407 a->xdi_adapter.port = (void *) (unsigned long) a->resources.pci.bar[1]; /* BAR1 */
408 a->xdi_adapter.ctlReg = (void *) (unsigned long) a->resources.pci.bar[3]; /* BAR3 CNTRL */
409
410 for (i = 0; i < tasks; i++) {
411 diva_current = adapter_list[i];
412 diva_4bri_set_addresses(diva_current);
413 Slave = a->xdi_adapter.QuadroList->QuadroAdapter[i];
414 Slave->MultiMaster = &a->xdi_adapter;
415 Slave->sdram_bar = a->xdi_adapter.sdram_bar;
416 if (i) {
417 Slave->serialNo = ((dword) (Slave->ControllerNumber << 24)) |
418 a->xdi_adapter.serialNo;
419 Slave->cardType = a->xdi_adapter.cardType;
420 }
421 }
422
423 /*
424 reset contains the base address for the PLX 9054 register set
425 */
426 p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter);
427 WRITE_BYTE(&p[PLX9054_INTCSR], 0x00); /* disable PCI interrupts */
428 DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p);
429
430 /*
431 Set IRQ handler
432 */
433 a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq;
434 sprintf(a->xdi_adapter.irq_info.irq_name, "DIVA 4BRI %ld",
435 (long) a->xdi_adapter.serialNo);
436
437 if (diva_os_register_irq(a, a->xdi_adapter.irq_info.irq_nr,
438 a->xdi_adapter.irq_info.irq_name)) {
439 diva_4bri_cleanup_slave_adapters(a);
440 diva_4bri_cleanup_adapter(a);
441 for (i = 1; i < (tasks - 1); i++) {
442 diva_os_free(0, adapter_list[i]);
443 }
444 return (-1);
445 }
446
447 a->xdi_adapter.irq_info.registered = 1;
448
449 /*
450 Add three slave adapters
451 */
452 if (tasks > 1) {
453 diva_add_slave_adapter(adapter_list[1]);
454 diva_add_slave_adapter(adapter_list[2]);
455 diva_add_slave_adapter(adapter_list[3]);
456 }
457
458 diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
459 a->resources.pci.irq, a->xdi_adapter.serialNo);
460
461 return (0);
462}
463
464/*
465** Cleanup function will be called for master adapter only
466** this is garanteed by design: cleanup callback is set
467** by master adapter only
468*/
469static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t * a)
470{
471 int bar;
472
473 /*
474 Stop adapter if running
475 */
476 if (a->xdi_adapter.Initialized) {
477 diva_4bri_stop_adapter(a);
478 }
479
480 /*
481 Remove IRQ handler
482 */
483 if (a->xdi_adapter.irq_info.registered) {
484 diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr);
485 }
486 a->xdi_adapter.irq_info.registered = 0;
487
488 /*
489 Free DPC's and spin locks on all adapters
490 */
491 diva_4bri_cleanup_slave_adapters(a);
492
493 /*
494 Unmap all BARS
495 */
496 for (bar = 0; bar < 4; bar++) {
497 if (bar != 1) {
498 if (a->resources.pci.bar[bar]
499 && a->resources.pci.addr[bar]) {
500 divasa_unmap_pci_bar(a->resources.pci.addr[bar]);
501 a->resources.pci.bar[bar] = 0;
502 a->resources.pci.addr[bar] = NULL;
503 }
504 }
505 }
506
507 /*
508 Unregister I/O
509 */
510 if (a->resources.pci.bar[1] && a->resources.pci.addr[1]) {
511 diva_os_register_io_port(a, 0, a->resources.pci.bar[1],
512 _4bri_is_rev_2_card(a->
513 CardOrdinal) ?
514 _4bri_v2_bar_length[1] :
515 _4bri_bar_length[1],
516 &a->port_name[0], 1);
517 a->resources.pci.bar[1] = 0;
518 a->resources.pci.addr[1] = NULL;
519 }
520
521 if (a->slave_list) {
522 diva_os_free(0, a->slave_list);
523 a->slave_list = NULL;
524 }
525
526 return (0);
527}
528
529static int _4bri_get_serial_number(diva_os_xdi_adapter_t * a)
530{
531 dword data[64];
532 dword serNo;
533 word addr, status, i, j;
534 byte Bus, Slot;
535 void *hdev;
536
537 Bus = a->resources.pci.bus;
538 Slot = a->resources.pci.func;
539 hdev = a->resources.pci.hdev;
540
541 for (i = 0; i < 64; ++i) {
542 addr = i * 4;
543 for (j = 0; j < 5; ++j) {
544 PCIwrite(Bus, Slot, 0x4E, &addr, sizeof(addr),
545 hdev);
546 diva_os_wait(1);
547 PCIread(Bus, Slot, 0x4E, &status, sizeof(status),
548 hdev);
549 if (status & 0x8000)
550 break;
551 }
552 if (j >= 5) {
553 DBG_ERR(("EEPROM[%d] read failed (0x%x)", i * 4, addr))
554 return (0);
555 }
556 PCIread(Bus, Slot, 0x50, &data[i], sizeof(data[i]), hdev);
557 }
558 DBG_BLK(((char *) &data[0], sizeof(data)))
559
560 serNo = data[32];
561 if (serNo == 0 || serNo == 0xffffffff)
562 serNo = data[63];
563
564 if (!serNo) {
565 DBG_LOG(("W: Serial Number == 0, create one serial number"));
566 serNo = a->resources.pci.bar[1] & 0xffff0000;
567 serNo |= a->resources.pci.bus << 8;
568 serNo |= a->resources.pci.func;
569 }
570
571 a->xdi_adapter.serialNo = serNo;
572
573 DBG_REG(("Serial No. : %ld", a->xdi_adapter.serialNo))
574
575 return (serNo);
576}
577
578/*
579** Release resources of slave adapters
580*/
581static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t * a)
582{
583 diva_os_xdi_adapter_t *adapter_list[4];
584 diva_os_xdi_adapter_t *diva_current;
585 int i;
586
587 adapter_list[0] = a;
588 adapter_list[1] = a->slave_adapters[0];
589 adapter_list[2] = a->slave_adapters[1];
590 adapter_list[3] = a->slave_adapters[2];
591
592 for (i = 0; i < a->xdi_adapter.tasks; i++) {
593 diva_current = adapter_list[i];
594 if (diva_current) {
595 diva_os_destroy_spin_lock(&diva_current->
596 xdi_adapter.
597 isr_spin_lock, "unload");
598 diva_os_destroy_spin_lock(&diva_current->
599 xdi_adapter.
600 data_spin_lock,
601 "unload");
602
603 diva_os_cancel_soft_isr(&diva_current->xdi_adapter.
604 req_soft_isr);
605 diva_os_cancel_soft_isr(&diva_current->xdi_adapter.
606 isr_soft_isr);
607
608 diva_os_remove_soft_isr(&diva_current->xdi_adapter.
609 req_soft_isr);
610 diva_current->xdi_adapter.isr_soft_isr.object = NULL;
611
612 if (diva_current->xdi_adapter.e_tbl) {
613 diva_os_free(0,
614 diva_current->xdi_adapter.
615 e_tbl);
616 }
617 diva_current->xdi_adapter.e_tbl = NULL;
618 diva_current->xdi_adapter.e_max = 0;
619 diva_current->xdi_adapter.e_count = 0;
620 }
621 }
622
623 return (0);
624}
625
626static int
627diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
628 diva_xdi_um_cfg_cmd_t * cmd, int length)
629{
630 int ret = -1;
631
632 if (cmd->adapter != a->controller) {
633 DBG_ERR(("A: 4bri_cmd, invalid controller=%d != %d",
634 cmd->adapter, a->controller))
635 return (-1);
636 }
637
638 switch (cmd->command) {
639 case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL:
640 a->xdi_mbox.data_length = sizeof(dword);
641 a->xdi_mbox.data =
642 diva_os_malloc(0, a->xdi_mbox.data_length);
643 if (a->xdi_mbox.data) {
644 *(dword *) a->xdi_mbox.data =
645 (dword) a->CardOrdinal;
646 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
647 ret = 0;
648 }
649 break;
650
651 case DIVA_XDI_UM_CMD_GET_SERIAL_NR:
652 a->xdi_mbox.data_length = sizeof(dword);
653 a->xdi_mbox.data =
654 diva_os_malloc(0, a->xdi_mbox.data_length);
655 if (a->xdi_mbox.data) {
656 *(dword *) a->xdi_mbox.data =
657 (dword) a->xdi_adapter.serialNo;
658 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
659 ret = 0;
660 }
661 break;
662
663 case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
664 if (!a->xdi_adapter.ControllerNumber) {
665 /*
666 Only master adapter can access hardware config
667 */
668 a->xdi_mbox.data_length = sizeof(dword) * 9;
669 a->xdi_mbox.data =
670 diva_os_malloc(0, a->xdi_mbox.data_length);
671 if (a->xdi_mbox.data) {
672 int i;
673 dword *data = (dword *) a->xdi_mbox.data;
674
675 for (i = 0; i < 8; i++) {
676 *data++ = a->resources.pci.bar[i];
677 }
678 *data++ = (dword) a->resources.pci.irq;
679 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
680 ret = 0;
681 }
682 }
683 break;
684
685 case DIVA_XDI_UM_CMD_GET_CARD_STATE:
686 if (!a->xdi_adapter.ControllerNumber) {
687 a->xdi_mbox.data_length = sizeof(dword);
688 a->xdi_mbox.data =
689 diva_os_malloc(0, a->xdi_mbox.data_length);
690 if (a->xdi_mbox.data) {
691 dword *data = (dword *) a->xdi_mbox.data;
692 if (!a->xdi_adapter.ram
693 || !a->xdi_adapter.reset
694 || !a->xdi_adapter.cfg) {
695 *data = 3;
696 } else if (a->xdi_adapter.trapped) {
697 *data = 2;
698 } else if (a->xdi_adapter.Initialized) {
699 *data = 1;
700 } else {
701 *data = 0;
702 }
703 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
704 ret = 0;
705 }
706 }
707 break;
708
709 case DIVA_XDI_UM_CMD_WRITE_FPGA:
710 if (!a->xdi_adapter.ControllerNumber) {
711 ret =
712 diva_4bri_write_fpga_image(a,
713 (byte *) & cmd[1],
714 cmd->command_data.
715 write_fpga.
716 image_length);
717 }
718 break;
719
720 case DIVA_XDI_UM_CMD_RESET_ADAPTER:
721 if (!a->xdi_adapter.ControllerNumber) {
722 ret = diva_4bri_reset_adapter(&a->xdi_adapter);
723 }
724 break;
725
726 case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK:
727 if (!a->xdi_adapter.ControllerNumber) {
728 ret = diva_4bri_write_sdram_block(&a->xdi_adapter,
729 cmd->
730 command_data.
731 write_sdram.
732 offset,
733 (byte *) &
734 cmd[1],
735 cmd->
736 command_data.
737 write_sdram.
738 length,
739 a->xdi_adapter.
740 MemorySize);
741 }
742 break;
743
744 case DIVA_XDI_UM_CMD_START_ADAPTER:
745 if (!a->xdi_adapter.ControllerNumber) {
746 ret = diva_4bri_start_adapter(&a->xdi_adapter,
747 cmd->command_data.
748 start.offset,
749 cmd->command_data.
750 start.features);
751 }
752 break;
753
754 case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES:
755 if (!a->xdi_adapter.ControllerNumber) {
756 a->xdi_adapter.features =
757 cmd->command_data.features.features;
758 a->xdi_adapter.a.protocol_capabilities =
759 a->xdi_adapter.features;
760 DBG_TRC(("Set raw protocol features (%08x)",
761 a->xdi_adapter.features))
762 ret = 0;
763 }
764 break;
765
766 case DIVA_XDI_UM_CMD_STOP_ADAPTER:
767 if (!a->xdi_adapter.ControllerNumber) {
768 ret = diva_4bri_stop_adapter(a);
769 }
770 break;
771
772 case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
773 ret = diva_card_read_xlog(a);
774 break;
775
776 case DIVA_XDI_UM_CMD_READ_SDRAM:
777 if (!a->xdi_adapter.ControllerNumber
778 && a->xdi_adapter.Address) {
779 if (
780 (a->xdi_mbox.data_length =
781 cmd->command_data.read_sdram.length)) {
782 if (
783 (a->xdi_mbox.data_length +
784 cmd->command_data.read_sdram.offset) <
785 a->xdi_adapter.MemorySize) {
786 a->xdi_mbox.data =
787 diva_os_malloc(0,
788 a->xdi_mbox.
789 data_length);
790 if (a->xdi_mbox.data) {
791 byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(&a->xdi_adapter);
792 byte __iomem *src = p;
793 byte *dst = a->xdi_mbox.data;
794 dword len = a->xdi_mbox.data_length;
795
796 src += cmd->command_data.read_sdram.offset;
797
798 while (len--) {
799 *dst++ = READ_BYTE(src++);
800 }
801 DIVA_OS_MEM_DETACH_ADDRESS(&a->xdi_adapter, p);
802 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
803 ret = 0;
804 }
805 }
806 }
807 }
808 break;
809
810 default:
811 DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller,
812 cmd->command))
813 }
814
815 return (ret);
816}
817
818void *xdiLoadFile(char *FileName, unsigned long *FileLength,
819 unsigned long lim)
820{
821 void *ret = diva_xdiLoadFileFile;
822
823 if (FileLength) {
824 *FileLength = diva_xdiLoadFileLength;
825 }
826 diva_xdiLoadFileFile = NULL;
827 diva_xdiLoadFileLength = 0;
828
829 return (ret);
830}
831
832void diva_os_set_qBri_functions(PISDN_ADAPTER IoAdapter)
833{
834}
835
836void diva_os_set_qBri2_functions(PISDN_ADAPTER IoAdapter)
837{
838}
839
840static int
841diva_4bri_write_fpga_image(diva_os_xdi_adapter_t * a, byte * data,
842 dword length)
843{
844 int ret;
845
846 diva_xdiLoadFileFile = data;
847 diva_xdiLoadFileLength = length;
848
849 ret = qBri_FPGA_download(&a->xdi_adapter);
850
851 diva_xdiLoadFileFile = NULL;
852 diva_xdiLoadFileLength = 0;
853
854 return (ret ? 0 : -1);
855}
856
857static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter)
858{
859 PISDN_ADAPTER Slave;
860 int i;
861
862 if (!IoAdapter->Address || !IoAdapter->reset) {
863 return (-1);
864 }
865 if (IoAdapter->Initialized) {
866 DBG_ERR(("A: A(%d) can't reset 4BRI adapter - please stop first",
867 IoAdapter->ANum))
868 return (-1);
869 }
870
871 /*
872 Forget all entities on all adapters
873 */
874 for (i = 0; ((i < IoAdapter->tasks) && IoAdapter->QuadroList); i++) {
875 Slave = IoAdapter->QuadroList->QuadroAdapter[i];
876 Slave->e_count = 0;
877 if (Slave->e_tbl) {
878 memset(Slave->e_tbl, 0x00,
879 Slave->e_max * sizeof(E_INFO));
880 }
881 Slave->head = 0;
882 Slave->tail = 0;
883 Slave->assign = 0;
884 Slave->trapped = 0;
885
886 memset(&Slave->a.IdTable[0], 0x00,
887 sizeof(Slave->a.IdTable));
888 memset(&Slave->a.IdTypeTable[0], 0x00,
889 sizeof(Slave->a.IdTypeTable));
890 memset(&Slave->a.FlowControlIdTable[0], 0x00,
891 sizeof(Slave->a.FlowControlIdTable));
892 memset(&Slave->a.FlowControlSkipTable[0], 0x00,
893 sizeof(Slave->a.FlowControlSkipTable));
894 memset(&Slave->a.misc_flags_table[0], 0x00,
895 sizeof(Slave->a.misc_flags_table));
896 memset(&Slave->a.rx_stream[0], 0x00,
897 sizeof(Slave->a.rx_stream));
898 memset(&Slave->a.tx_stream[0], 0x00,
899 sizeof(Slave->a.tx_stream));
900 memset(&Slave->a.tx_pos[0], 0x00, sizeof(Slave->a.tx_pos));
901 memset(&Slave->a.rx_pos[0], 0x00, sizeof(Slave->a.rx_pos));
902 }
903
904 return (0);
905}
906
907
908static int
909diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
910 dword address,
911 const byte * data, dword length, dword limit)
912{
913 byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
914 byte __iomem *mem = p;
915
916 if (((address + length) >= limit) || !mem) {
917 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
918 DBG_ERR(("A: A(%d) write 4BRI address=0x%08lx",
919 IoAdapter->ANum, address + length))
920 return (-1);
921 }
922 mem += address;
923
924 while (length--) {
925 WRITE_BYTE(mem++, *data++);
926 }
927
928 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
929 return (0);
930}
931
932static int
933diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
934 dword start_address, dword features)
935{
936 volatile word __iomem *signature;
937 int started = 0;
938 int i;
939 byte __iomem *p;
940
941 /*
942 start adapter
943 */
944 start_qBri_hardware(IoAdapter);
945
946 p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter);
947 /*
948 wait for signature in shared memory (max. 3 seconds)
949 */
950 signature = (volatile word __iomem *) (&p[0x1E]);
951
952 for (i = 0; i < 300; ++i) {
953 diva_os_wait(10);
954 if (READ_WORD(&signature[0]) == 0x4447) {
955 DBG_TRC(("Protocol startup time %d.%02d seconds",
956 (i / 100), (i % 100)))
957 started = 1;
958 break;
959 }
960 }
961
962 for (i = 1; i < IoAdapter->tasks; i++) {
963 IoAdapter->QuadroList->QuadroAdapter[i]->features =
964 IoAdapter->features;
965 IoAdapter->QuadroList->QuadroAdapter[i]->a.
966 protocol_capabilities = IoAdapter->features;
967 }
968
969 if (!started) {
970 DBG_FTL(("%s: Adapter selftest failed, signature=%04x",
971 IoAdapter->Properties.Name,
972 READ_WORD(&signature[0])))
973 DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
974 (*(IoAdapter->trapFnc)) (IoAdapter);
975 IoAdapter->stop(IoAdapter);
976 return (-1);
977 }
978 DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
979
980 for (i = 0; i < IoAdapter->tasks; i++) {
981 IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 1;
982 IoAdapter->QuadroList->QuadroAdapter[i]->IrqCount = 0;
983 }
984
985 if (check_qBri_interrupt(IoAdapter)) {
986 DBG_ERR(("A: A(%d) interrupt test failed",
987 IoAdapter->ANum))
988 for (i = 0; i < IoAdapter->tasks; i++) {
989 IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
990 }
991 IoAdapter->stop(IoAdapter);
992 return (-1);
993 }
994
995 IoAdapter->Properties.Features = (word) features;
996 diva_xdi_display_adapter_features(IoAdapter->ANum);
997
998 for (i = 0; i < IoAdapter->tasks; i++) {
999 DBG_LOG(("A(%d) %s adapter successfull started",
1000 IoAdapter->QuadroList->QuadroAdapter[i]->ANum,
1001 (IoAdapter->tasks == 1) ? "BRI 2.0" : "4BRI"))
1002 diva_xdi_didd_register_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
1003 IoAdapter->QuadroList->QuadroAdapter[i]->Properties.Features = (word) features;
1004 }
1005
1006 return (0);
1007}
1008
1009static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter)
1010{
1011#ifdef SUPPORT_INTERRUPT_TEST_ON_4BRI
1012 int i;
1013 ADAPTER *a = &IoAdapter->a;
1014 byte __iomem *p;
1015
1016 IoAdapter->IrqCount = 0;
1017
1018 if (IoAdapter->ControllerNumber > 0)
1019 return (-1);
1020
1021 p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
1022 WRITE_BYTE(&p[PLX9054_INTCSR], PLX9054_INT_ENABLE);
1023 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
1024 /*
1025 interrupt test
1026 */
1027 a->ReadyInt = 1;
1028 a->ram_out(a, &PR_RAM->ReadyInt, 1);
1029
1030 for (i = 100; !IoAdapter->IrqCount && (i-- > 0); diva_os_wait(10));
1031
1032 return ((IoAdapter->IrqCount > 0) ? 0 : -1);
1033#else
1034 dword volatile __iomem *qBriIrq;
1035 byte __iomem *p;
1036 /*
1037 Reset on-board interrupt register
1038 */
1039 IoAdapter->IrqCount = 0;
1040 p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
1041 qBriIrq = (dword volatile __iomem *) (&p[_4bri_is_rev_2_card
1042 (IoAdapter->
1043 cardType) ? (MQ2_BREG_IRQ_TEST)
1044 : (MQ_BREG_IRQ_TEST)]);
1045
1046 WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
1047 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
1048
1049 p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
1050 WRITE_BYTE(&p[PLX9054_INTCSR], PLX9054_INT_ENABLE);
1051 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
1052
1053 diva_os_wait(100);
1054
1055 return (0);
1056#endif /* SUPPORT_INTERRUPT_TEST_ON_4BRI */
1057}
1058
1059static void diva_4bri_clear_interrupts(diva_os_xdi_adapter_t * a)
1060{
1061 PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
1062
1063 /*
1064 clear any pending interrupt
1065 */
1066 IoAdapter->disIrq(IoAdapter);
1067
1068 IoAdapter->tst_irq(&IoAdapter->a);
1069 IoAdapter->clr_irq(&IoAdapter->a);
1070 IoAdapter->tst_irq(&IoAdapter->a);
1071
1072 /*
1073 kill pending dpcs
1074 */
1075 diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
1076 diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
1077}
1078
1079static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t * a)
1080{
1081 PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
1082 int i;
1083
1084 if (!IoAdapter->ram) {
1085 return (-1);
1086 }
1087
1088 if (!IoAdapter->Initialized) {
1089 DBG_ERR(("A: A(%d) can't stop PRI adapter - not running",
1090 IoAdapter->ANum))
1091 return (-1); /* nothing to stop */
1092 }
1093
1094 for (i = 0; i < IoAdapter->tasks; i++) {
1095 IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
1096 }
1097
1098 /*
1099 Disconnect Adapters from DIDD
1100 */
1101 for (i = 0; i < IoAdapter->tasks; i++) {
1102 diva_xdi_didd_remove_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
1103 }
1104
1105 i = 100;
1106
1107 /*
1108 Stop interrupts
1109 */
1110 a->clear_interrupts_proc = diva_4bri_clear_interrupts;
1111 IoAdapter->a.ReadyInt = 1;
1112 IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt);
1113 do {
1114 diva_os_sleep(10);
1115 } while (i-- && a->clear_interrupts_proc);
1116
1117 if (a->clear_interrupts_proc) {
1118 diva_4bri_clear_interrupts(a);
1119 a->clear_interrupts_proc = NULL;
1120 DBG_ERR(("A: A(%d) no final interrupt from 4BRI adapter",
1121 IoAdapter->ANum))
1122 }
1123 IoAdapter->a.ReadyInt = 0;
1124
1125 /*
1126 Stop and reset adapter
1127 */
1128 IoAdapter->stop(IoAdapter);
1129
1130 return (0);
1131}
diff --git a/drivers/isdn/hardware/eicon/os_4bri.h b/drivers/isdn/hardware/eicon/os_4bri.h
new file mode 100644
index 000000000000..665f0af27ce7
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/os_4bri.h
@@ -0,0 +1,8 @@
1/* $Id: os_4bri.h,v 1.1.2.2 2001/02/08 12:25:44 armin Exp $ */
2
3#ifndef __DIVA_OS_4_BRI_H__
4#define __DIVA_OS_4_BRI_H__
5
6int diva_4bri_init_card(diva_os_xdi_adapter_t * a);
7
8#endif
diff --git a/drivers/isdn/hardware/eicon/os_bri.c b/drivers/isdn/hardware/eicon/os_bri.c
new file mode 100644
index 000000000000..4cc44a5dd1db
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/os_bri.c
@@ -0,0 +1,813 @@
1/* $Id: os_bri.c,v 1.21 2004/03/21 17:26:01 armin Exp $ */
2
3#include "platform.h"
4#include "debuglib.h"
5#include "cardtype.h"
6#include "pc.h"
7#include "pr_pc.h"
8#include "di_defs.h"
9#include "dsp_defs.h"
10#include "di.h"
11#include "io.h"
12
13#include "xdi_msg.h"
14#include "xdi_adapter.h"
15#include "os_bri.h"
16#include "diva_pci.h"
17#include "mi_pc.h"
18#include "pc_maint.h"
19
20/*
21** IMPORTS
22*/
23extern void prepare_maestra_functions(PISDN_ADAPTER IoAdapter);
24extern void diva_xdi_display_adapter_features(int card);
25extern int diva_card_read_xlog(diva_os_xdi_adapter_t * a);
26
27/*
28** LOCALS
29*/
30static int bri_bar_length[3] = {
31 0x80,
32 0x80,
33 0x20
34};
35static int diva_bri_cleanup_adapter(diva_os_xdi_adapter_t * a);
36static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t * a);
37static int diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
38 diva_xdi_um_cfg_cmd_t * cmd, int length);
39static int diva_bri_reregister_io(diva_os_xdi_adapter_t * a);
40static int diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter);
41static int diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
42 dword address,
43 const byte * data, dword length);
44static int diva_bri_start_adapter(PISDN_ADAPTER IoAdapter,
45 dword start_address, dword features);
46static int diva_bri_stop_adapter(diva_os_xdi_adapter_t * a);
47
48static void diva_bri_set_addresses(diva_os_xdi_adapter_t * a)
49{
50 a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 0;
51 a->resources.pci.mem_type_id[MEM_TYPE_CFG] = 1;
52 a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 2;
53 a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 1;
54 a->resources.pci.mem_type_id[MEM_TYPE_PORT] = 2;
55 a->resources.pci.mem_type_id[MEM_TYPE_CTLREG] = 2;
56
57 a->xdi_adapter.ram = a->resources.pci.addr[0];
58 a->xdi_adapter.cfg = a->resources.pci.addr[1];
59 a->xdi_adapter.Address = a->resources.pci.addr[2];
60
61 a->xdi_adapter.reset = a->xdi_adapter.cfg;
62 a->xdi_adapter.port = a->xdi_adapter.Address;
63
64 a->xdi_adapter.ctlReg = a->xdi_adapter.port + M_PCI_RESET;
65
66 a->xdi_adapter.reset += 0x4C; /* PLX 9050 !! */
67}
68
69/*
70** BAR0 - MEM Addr - 0x80 - NOT USED
71** BAR1 - I/O Addr - 0x80
72** BAR2 - I/O Addr - 0x20
73*/
74int diva_bri_init_card(diva_os_xdi_adapter_t * a)
75{
76 int bar;
77 dword bar2 = 0, bar2_length = 0xffffffff;
78 word cmd = 0, cmd_org;
79 byte Bus, Slot;
80 void *hdev;
81 byte __iomem *p;
82
83 /*
84 Set properties
85 */
86 a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
87 DBG_LOG(("Load %s", a->xdi_adapter.Properties.Name))
88
89 /*
90 Get resources
91 */
92 for (bar = 0; bar < 3; bar++) {
93 a->resources.pci.bar[bar] =
94 divasa_get_pci_bar(a->resources.pci.bus,
95 a->resources.pci.func, bar,
96 a->resources.pci.hdev);
97 if (!a->resources.pci.bar[bar]) {
98 DBG_ERR(("A: can't get BAR[%d]", bar))
99 return (-1);
100 }
101 }
102
103 a->resources.pci.irq =
104 (byte) divasa_get_pci_irq(a->resources.pci.bus,
105 a->resources.pci.func,
106 a->resources.pci.hdev);
107 if (!a->resources.pci.irq) {
108 DBG_ERR(("A: invalid irq"));
109 return (-1);
110 }
111
112 /*
113 Get length of I/O bar 2 - it is different by older
114 EEPROM version
115 */
116 Bus = a->resources.pci.bus;
117 Slot = a->resources.pci.func;
118 hdev = a->resources.pci.hdev;
119
120 /*
121 Get plain original values of the BAR2 CDM registers
122 */
123 PCIread(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev);
124 PCIread(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
125 /*
126 Disable device and get BAR2 length
127 */
128 PCIwrite(Bus, Slot, 0x04, &cmd, sizeof(cmd), hdev);
129 PCIwrite(Bus, Slot, 0x18, &bar2_length, sizeof(bar2_length), hdev);
130 PCIread(Bus, Slot, 0x18, &bar2_length, sizeof(bar2_length), hdev);
131 /*
132 Restore BAR2 and CMD registers
133 */
134 PCIwrite(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev);
135 PCIwrite(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
136
137 /*
138 Calculate BAR2 length
139 */
140 bar2_length = (~(bar2_length & ~7)) + 1;
141 DBG_LOG(("BAR[2] length=%lx", bar2_length))
142
143 /*
144 Map and register resources
145 */
146 if (!(a->resources.pci.addr[0] =
147 divasa_remap_pci_bar(a, 0, a->resources.pci.bar[0],
148 bri_bar_length[0]))) {
149 DBG_ERR(("A: BRI, can't map BAR[0]"))
150 diva_bri_cleanup_adapter(a);
151 return (-1);
152 }
153
154 sprintf(&a->port_name[0], "BRI %02x:%02x",
155 a->resources.pci.bus, a->resources.pci.func);
156
157 if (diva_os_register_io_port(a, 1, a->resources.pci.bar[1],
158 bri_bar_length[1], &a->port_name[0], 1)) {
159 DBG_ERR(("A: BRI, can't register BAR[1]"))
160 diva_bri_cleanup_adapter(a);
161 return (-1);
162 }
163 a->resources.pci.addr[1] = (void *) (unsigned long) a->resources.pci.bar[1];
164 a->resources.pci.length[1] = bri_bar_length[1];
165
166 if (diva_os_register_io_port(a, 1, a->resources.pci.bar[2],
167 bar2_length, &a->port_name[0], 2)) {
168 DBG_ERR(("A: BRI, can't register BAR[2]"))
169 diva_bri_cleanup_adapter(a);
170 return (-1);
171 }
172 a->resources.pci.addr[2] = (void *) (unsigned long) a->resources.pci.bar[2];
173 a->resources.pci.length[2] = bar2_length;
174
175 /*
176 Set all memory areas
177 */
178 diva_bri_set_addresses(a);
179
180 /*
181 Get Serial Number
182 */
183 a->xdi_adapter.serialNo = diva_bri_get_serial_number(a);
184
185 /*
186 Register I/O ports with correct name now
187 */
188 if (diva_bri_reregister_io(a)) {
189 diva_bri_cleanup_adapter(a);
190 return (-1);
191 }
192
193 /*
194 Initialize OS dependent objects
195 */
196 if (diva_os_initialize_spin_lock
197 (&a->xdi_adapter.isr_spin_lock, "isr")) {
198 diva_bri_cleanup_adapter(a);
199 return (-1);
200 }
201 if (diva_os_initialize_spin_lock
202 (&a->xdi_adapter.data_spin_lock, "data")) {
203 diva_bri_cleanup_adapter(a);
204 return (-1);
205 }
206
207 strcpy(a->xdi_adapter.req_soft_isr.dpc_thread_name, "kdivasbrid");
208
209 if (diva_os_initialize_soft_isr(&a->xdi_adapter.req_soft_isr,
210 DIDpcRoutine, &a->xdi_adapter)) {
211 diva_bri_cleanup_adapter(a);
212 return (-1);
213 }
214 /*
215 Do not initialize second DPC - only one thread will be created
216 */
217 a->xdi_adapter.isr_soft_isr.object = a->xdi_adapter.req_soft_isr.object;
218
219 /*
220 Create entity table
221 */
222 a->xdi_adapter.Channels = CardProperties[a->CardOrdinal].Channels;
223 a->xdi_adapter.e_max = CardProperties[a->CardOrdinal].E_info;
224 a->xdi_adapter.e_tbl = diva_os_malloc(0, a->xdi_adapter.e_max * sizeof(E_INFO));
225 if (!a->xdi_adapter.e_tbl) {
226 diva_bri_cleanup_adapter(a);
227 return (-1);
228 }
229 memset(a->xdi_adapter.e_tbl, 0x00, a->xdi_adapter.e_max * sizeof(E_INFO));
230
231 /*
232 Set up interface
233 */
234 a->xdi_adapter.a.io = &a->xdi_adapter;
235 a->xdi_adapter.DIRequest = request;
236 a->interface.cleanup_adapter_proc = diva_bri_cleanup_adapter;
237 a->interface.cmd_proc = diva_bri_cmd_card_proc;
238
239 p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter);
240 outpp(p, 0x41);
241 DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p);
242
243 prepare_maestra_functions(&a->xdi_adapter);
244
245 a->dsp_mask = 0x00000003;
246
247 /*
248 Set IRQ handler
249 */
250 a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq;
251 sprintf(a->xdi_adapter.irq_info.irq_name, "DIVA BRI %ld",
252 (long) a->xdi_adapter.serialNo);
253 if (diva_os_register_irq(a, a->xdi_adapter.irq_info.irq_nr,
254 a->xdi_adapter.irq_info.irq_name)) {
255 diva_bri_cleanup_adapter(a);
256 return (-1);
257 }
258 a->xdi_adapter.irq_info.registered = 1;
259
260 diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
261 a->resources.pci.irq, a->xdi_adapter.serialNo);
262
263 return (0);
264}
265
266
267static int diva_bri_cleanup_adapter(diva_os_xdi_adapter_t * a)
268{
269 int i;
270
271 if (a->xdi_adapter.Initialized) {
272 diva_bri_stop_adapter(a);
273 }
274
275 /*
276 Remove ISR Handler
277 */
278 if (a->xdi_adapter.irq_info.registered) {
279 diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr);
280 }
281 a->xdi_adapter.irq_info.registered = 0;
282
283 if (a->resources.pci.addr[0] && a->resources.pci.bar[0]) {
284 divasa_unmap_pci_bar(a->resources.pci.addr[0]);
285 a->resources.pci.addr[0] = NULL;
286 a->resources.pci.bar[0] = 0;
287 }
288
289 for (i = 1; i < 3; i++) {
290 if (a->resources.pci.addr[i] && a->resources.pci.bar[i]) {
291 diva_os_register_io_port(a, 0,
292 a->resources.pci.bar[i],
293 a->resources.pci.
294 length[i],
295 &a->port_name[0], i);
296 a->resources.pci.addr[i] = NULL;
297 a->resources.pci.bar[i] = 0;
298 }
299 }
300
301 /*
302 Free OS objects
303 */
304 diva_os_cancel_soft_isr(&a->xdi_adapter.req_soft_isr);
305 diva_os_cancel_soft_isr(&a->xdi_adapter.isr_soft_isr);
306
307 diva_os_remove_soft_isr(&a->xdi_adapter.req_soft_isr);
308 a->xdi_adapter.isr_soft_isr.object = NULL;
309
310 diva_os_destroy_spin_lock(&a->xdi_adapter.isr_spin_lock, "rm");
311 diva_os_destroy_spin_lock(&a->xdi_adapter.data_spin_lock, "rm");
312
313 /*
314 Free memory
315 */
316 if (a->xdi_adapter.e_tbl) {
317 diva_os_free(0, a->xdi_adapter.e_tbl);
318 a->xdi_adapter.e_tbl = NULL;
319 }
320
321 return (0);
322}
323
324void diva_os_prepare_maestra_functions(PISDN_ADAPTER IoAdapter)
325{
326}
327
328/*
329** Get serial number
330*/
331static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t * a)
332{
333 dword serNo = 0;
334 byte __iomem *confIO;
335 word serHi, serLo;
336 word __iomem *confMem;
337
338 confIO = DIVA_OS_MEM_ATTACH_CFG(&a->xdi_adapter);
339 serHi = (word) (inppw(&confIO[0x22]) & 0x0FFF);
340 serLo = (word) (inppw(&confIO[0x26]) & 0x0FFF);
341 serNo = ((dword) serHi << 16) | (dword) serLo;
342 DIVA_OS_MEM_DETACH_CFG(&a->xdi_adapter, confIO);
343
344 if ((serNo == 0) || (serNo == 0xFFFFFFFF)) {
345 DBG_FTL(("W: BRI use BAR[0] to get card serial number"))
346
347 confMem = (word __iomem *)DIVA_OS_MEM_ATTACH_RAM(&a->xdi_adapter);
348 serHi = (word) (READ_WORD(&confMem[0x11]) & 0x0FFF);
349 serLo = (word) (READ_WORD(&confMem[0x13]) & 0x0FFF);
350 serNo = (((dword) serHi) << 16) | ((dword) serLo);
351 DIVA_OS_MEM_DETACH_RAM(&a->xdi_adapter, confMem);
352 }
353
354 DBG_LOG(("Serial Number=%ld", serNo))
355
356 return (serNo);
357}
358
359/*
360** Unregister I/O and register it with new name,
361** based on Serial Number
362*/
363static int diva_bri_reregister_io(diva_os_xdi_adapter_t * a)
364{
365 int i;
366
367 for (i = 1; i < 3; i++) {
368 diva_os_register_io_port(a, 0, a->resources.pci.bar[i],
369 a->resources.pci.length[i],
370 &a->port_name[0], i);
371 a->resources.pci.addr[i] = NULL;
372 }
373
374 sprintf(a->port_name, "DIVA BRI %ld",
375 (long) a->xdi_adapter.serialNo);
376
377 for (i = 1; i < 3; i++) {
378 if (diva_os_register_io_port(a, 1, a->resources.pci.bar[i],
379 a->resources.pci.length[i],
380 &a->port_name[0], i)) {
381 DBG_ERR(("A: failed to reregister BAR[%d]", i))
382 return (-1);
383 }
384 a->resources.pci.addr[i] =
385 (void *) (unsigned long) a->resources.pci.bar[i];
386 }
387
388 return (0);
389}
390
391/*
392** Process command from user mode
393*/
394static int
395diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
396 diva_xdi_um_cfg_cmd_t * cmd, int length)
397{
398 int ret = -1;
399
400 if (cmd->adapter != a->controller) {
401 DBG_ERR(("A: pri_cmd, invalid controller=%d != %d",
402 cmd->adapter, a->controller))
403 return (-1);
404 }
405
406 switch (cmd->command) {
407 case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL:
408 a->xdi_mbox.data_length = sizeof(dword);
409 a->xdi_mbox.data =
410 diva_os_malloc(0, a->xdi_mbox.data_length);
411 if (a->xdi_mbox.data) {
412 *(dword *) a->xdi_mbox.data =
413 (dword) a->CardOrdinal;
414 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
415 ret = 0;
416 }
417 break;
418
419 case DIVA_XDI_UM_CMD_GET_SERIAL_NR:
420 a->xdi_mbox.data_length = sizeof(dword);
421 a->xdi_mbox.data =
422 diva_os_malloc(0, a->xdi_mbox.data_length);
423 if (a->xdi_mbox.data) {
424 *(dword *) a->xdi_mbox.data =
425 (dword) a->xdi_adapter.serialNo;
426 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
427 ret = 0;
428 }
429 break;
430
431 case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
432 a->xdi_mbox.data_length = sizeof(dword) * 9;
433 a->xdi_mbox.data =
434 diva_os_malloc(0, a->xdi_mbox.data_length);
435 if (a->xdi_mbox.data) {
436 int i;
437 dword *data = (dword *) a->xdi_mbox.data;
438
439 for (i = 0; i < 8; i++) {
440 *data++ = a->resources.pci.bar[i];
441 }
442 *data++ = (dword) a->resources.pci.irq;
443 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
444 ret = 0;
445 }
446 break;
447
448 case DIVA_XDI_UM_CMD_GET_CARD_STATE:
449 a->xdi_mbox.data_length = sizeof(dword);
450 a->xdi_mbox.data =
451 diva_os_malloc(0, a->xdi_mbox.data_length);
452 if (a->xdi_mbox.data) {
453 dword *data = (dword *) a->xdi_mbox.data;
454 if (!a->xdi_adapter.port) {
455 *data = 3;
456 } else if (a->xdi_adapter.trapped) {
457 *data = 2;
458 } else if (a->xdi_adapter.Initialized) {
459 *data = 1;
460 } else {
461 *data = 0;
462 }
463 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
464 ret = 0;
465 }
466 break;
467
468 case DIVA_XDI_UM_CMD_RESET_ADAPTER:
469 ret = diva_bri_reset_adapter(&a->xdi_adapter);
470 break;
471
472 case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK:
473 ret = diva_bri_write_sdram_block(&a->xdi_adapter,
474 cmd->command_data.
475 write_sdram.offset,
476 (byte *) & cmd[1],
477 cmd->command_data.
478 write_sdram.length);
479 break;
480
481 case DIVA_XDI_UM_CMD_START_ADAPTER:
482 ret = diva_bri_start_adapter(&a->xdi_adapter,
483 cmd->command_data.start.
484 offset,
485 cmd->command_data.start.
486 features);
487 break;
488
489 case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES:
490 a->xdi_adapter.features =
491 cmd->command_data.features.features;
492 a->xdi_adapter.a.protocol_capabilities =
493 a->xdi_adapter.features;
494 DBG_TRC(
495 ("Set raw protocol features (%08x)",
496 a->xdi_adapter.features)) ret = 0;
497 break;
498
499 case DIVA_XDI_UM_CMD_STOP_ADAPTER:
500 ret = diva_bri_stop_adapter(a);
501 break;
502
503 case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
504 ret = diva_card_read_xlog(a);
505 break;
506
507 default:
508 DBG_ERR(
509 ("A: A(%d) invalid cmd=%d", a->controller,
510 cmd->command))}
511
512 return (ret);
513}
514
515static int diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter)
516{
517 byte __iomem *addrHi, *addrLo, *ioaddr;
518 dword i;
519 byte __iomem *Port;
520
521 if (!IoAdapter->port) {
522 return (-1);
523 }
524 if (IoAdapter->Initialized) {
525 DBG_ERR(("A: A(%d) can't reset BRI adapter - please stop first",
526 IoAdapter->ANum)) return (-1);
527 }
528 (*(IoAdapter->rstFnc)) (IoAdapter);
529 diva_os_wait(100);
530 Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter);
531 addrHi = Port +
532 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
533 addrLo = Port + ADDR;
534 ioaddr = Port + DATA;
535 /*
536 recover
537 */
538 outpp(addrHi, (byte) 0);
539 outppw(addrLo, (word) 0);
540 outppw(ioaddr, (word) 0);
541 /*
542 clear shared memory
543 */
544 outpp(addrHi,
545 (byte) (
546 (IoAdapter->MemoryBase + IoAdapter->MemorySize -
547 BRI_SHARED_RAM_SIZE) >> 16));
548 outppw(addrLo, 0);
549 for (i = 0; i < 0x8000; outppw(ioaddr, 0), ++i);
550 diva_os_wait(100);
551
552 /*
553 clear signature
554 */
555 outpp(addrHi,
556 (byte) (
557 (IoAdapter->MemoryBase + IoAdapter->MemorySize -
558 BRI_SHARED_RAM_SIZE) >> 16));
559 outppw(addrLo, 0x1e);
560 outpp(ioaddr, 0);
561 outpp(ioaddr, 0);
562
563 outpp(addrHi, (byte) 0);
564 outppw(addrLo, (word) 0);
565 outppw(ioaddr, (word) 0);
566
567 DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port);
568
569 /*
570 Forget all outstanding entities
571 */
572 IoAdapter->e_count = 0;
573 if (IoAdapter->e_tbl) {
574 memset(IoAdapter->e_tbl, 0x00,
575 IoAdapter->e_max * sizeof(E_INFO));
576 }
577 IoAdapter->head = 0;
578 IoAdapter->tail = 0;
579 IoAdapter->assign = 0;
580 IoAdapter->trapped = 0;
581
582 memset(&IoAdapter->a.IdTable[0], 0x00,
583 sizeof(IoAdapter->a.IdTable));
584 memset(&IoAdapter->a.IdTypeTable[0], 0x00,
585 sizeof(IoAdapter->a.IdTypeTable));
586 memset(&IoAdapter->a.FlowControlIdTable[0], 0x00,
587 sizeof(IoAdapter->a.FlowControlIdTable));
588 memset(&IoAdapter->a.FlowControlSkipTable[0], 0x00,
589 sizeof(IoAdapter->a.FlowControlSkipTable));
590 memset(&IoAdapter->a.misc_flags_table[0], 0x00,
591 sizeof(IoAdapter->a.misc_flags_table));
592 memset(&IoAdapter->a.rx_stream[0], 0x00,
593 sizeof(IoAdapter->a.rx_stream));
594 memset(&IoAdapter->a.tx_stream[0], 0x00,
595 sizeof(IoAdapter->a.tx_stream));
596 memset(&IoAdapter->a.tx_pos[0], 0x00, sizeof(IoAdapter->a.tx_pos));
597 memset(&IoAdapter->a.rx_pos[0], 0x00, sizeof(IoAdapter->a.rx_pos));
598
599 return (0);
600}
601
602static int
603diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
604 dword address, const byte * data, dword length)
605{
606 byte __iomem *addrHi, *addrLo, *ioaddr;
607 byte __iomem *Port;
608
609 if (!IoAdapter->port) {
610 return (-1);
611 }
612
613 Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter);
614 addrHi = Port +
615 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
616 addrLo = Port + ADDR;
617 ioaddr = Port + DATA;
618
619 while (length--) {
620 outpp(addrHi, (word) (address >> 16));
621 outppw(addrLo, (word) (address & 0x0000ffff));
622 outpp(ioaddr, *data++);
623 address++;
624 }
625
626 DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port);
627 return (0);
628}
629
630static int
631diva_bri_start_adapter(PISDN_ADAPTER IoAdapter,
632 dword start_address, dword features)
633{
634 byte __iomem *Port;
635 dword i, test;
636 byte __iomem *addrHi, *addrLo, *ioaddr;
637 int started = 0;
638 ADAPTER *a = &IoAdapter->a;
639
640 if (IoAdapter->Initialized) {
641 DBG_ERR(
642 ("A: A(%d) bri_start_adapter, adapter already running",
643 IoAdapter->ANum)) return (-1);
644 }
645 if (!IoAdapter->port) {
646 DBG_ERR(("A: A(%d) bri_start_adapter, adapter not mapped",
647 IoAdapter->ANum)) return (-1);
648 }
649
650 sprintf(IoAdapter->Name, "A(%d)", (int) IoAdapter->ANum);
651 DBG_LOG(("A(%d) start BRI", IoAdapter->ANum))
652
653 Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter);
654 addrHi = Port +
655 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
656 addrLo = Port + ADDR;
657 ioaddr = Port + DATA;
658
659 outpp(addrHi,
660 (byte) (
661 (IoAdapter->MemoryBase + IoAdapter->MemorySize -
662 BRI_SHARED_RAM_SIZE) >> 16));
663 outppw(addrLo, 0x1e);
664 outppw(ioaddr, 0x00);
665 DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port);
666
667 /*
668 start the protocol code
669 */
670 Port = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
671 outpp(Port, 0x08);
672 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, Port);
673
674 Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter);
675 addrHi = Port +
676 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
677 addrLo = Port + ADDR;
678 ioaddr = Port + DATA;
679 /*
680 wait for signature (max. 3 seconds)
681 */
682 for (i = 0; i < 300; ++i) {
683 diva_os_wait(10);
684 outpp(addrHi,
685 (byte) (
686 (IoAdapter->MemoryBase +
687 IoAdapter->MemorySize -
688 BRI_SHARED_RAM_SIZE) >> 16));
689 outppw(addrLo, 0x1e);
690 test = (dword) inppw(ioaddr);
691 if (test == 0x4447) {
692 DBG_LOG(
693 ("Protocol startup time %d.%02d seconds",
694 (i / 100), (i % 100)))
695 started = 1;
696 break;
697 }
698 }
699 DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port);
700
701 if (!started) {
702 DBG_FTL(("A: A(%d) %s: Adapter selftest failed 0x%04X",
703 IoAdapter->ANum, IoAdapter->Properties.Name,
704 test))
705 (*(IoAdapter->trapFnc)) (IoAdapter);
706 return (-1);
707 }
708
709 IoAdapter->Initialized = 1;
710
711 /*
712 Check Interrupt
713 */
714 IoAdapter->IrqCount = 0;
715 a->ReadyInt = 1;
716
717 if (IoAdapter->reset) {
718 Port = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
719 outpp(Port, 0x41);
720 DIVA_OS_MEM_DETACH_RESET(IoAdapter, Port);
721 }
722
723 a->ram_out(a, &PR_RAM->ReadyInt, 1);
724 for (i = 0; ((!IoAdapter->IrqCount) && (i < 100)); i++) {
725 diva_os_wait(10);
726 }
727 if (!IoAdapter->IrqCount) {
728 DBG_ERR(
729 ("A: A(%d) interrupt test failed",
730 IoAdapter->ANum))
731 IoAdapter->Initialized = 0;
732 IoAdapter->stop(IoAdapter);
733 return (-1);
734 }
735
736 IoAdapter->Properties.Features = (word) features;
737 diva_xdi_display_adapter_features(IoAdapter->ANum);
738 DBG_LOG(("A(%d) BRI adapter successfull started", IoAdapter->ANum))
739 /*
740 Register with DIDD
741 */
742 diva_xdi_didd_register_adapter(IoAdapter->ANum);
743
744 return (0);
745}
746
747static void diva_bri_clear_interrupts(diva_os_xdi_adapter_t * a)
748{
749 PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
750
751 /*
752 clear any pending interrupt
753 */
754 IoAdapter->disIrq(IoAdapter);
755
756 IoAdapter->tst_irq(&IoAdapter->a);
757 IoAdapter->clr_irq(&IoAdapter->a);
758 IoAdapter->tst_irq(&IoAdapter->a);
759
760 /*
761 kill pending dpcs
762 */
763 diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
764 diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
765}
766
767/*
768** Stop card
769*/
770static int diva_bri_stop_adapter(diva_os_xdi_adapter_t * a)
771{
772 PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
773 int i = 100;
774
775 if (!IoAdapter->port) {
776 return (-1);
777 }
778 if (!IoAdapter->Initialized) {
779 DBG_ERR(("A: A(%d) can't stop BRI adapter - not running",
780 IoAdapter->ANum))
781 return (-1); /* nothing to stop */
782 }
783 IoAdapter->Initialized = 0;
784
785 /*
786 Disconnect Adapter from DIDD
787 */
788 diva_xdi_didd_remove_adapter(IoAdapter->ANum);
789
790 /*
791 Stop interrupts
792 */
793 a->clear_interrupts_proc = diva_bri_clear_interrupts;
794 IoAdapter->a.ReadyInt = 1;
795 IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt);
796 do {
797 diva_os_sleep(10);
798 } while (i-- && a->clear_interrupts_proc);
799 if (a->clear_interrupts_proc) {
800 diva_bri_clear_interrupts(a);
801 a->clear_interrupts_proc = NULL;
802 DBG_ERR(("A: A(%d) no final interrupt from BRI adapter",
803 IoAdapter->ANum))
804 }
805 IoAdapter->a.ReadyInt = 0;
806
807 /*
808 Stop and reset adapter
809 */
810 IoAdapter->stop(IoAdapter);
811
812 return (0);
813}
diff --git a/drivers/isdn/hardware/eicon/os_bri.h b/drivers/isdn/hardware/eicon/os_bri.h
new file mode 100644
index 000000000000..a54f0ce58e13
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/os_bri.h
@@ -0,0 +1,8 @@
1/* $Id: os_bri.h,v 1.1.2.2 2001/02/08 12:25:44 armin Exp $ */
2
3#ifndef __DIVA_OS_BRI_REV_1_H__
4#define __DIVA_OS_BRI_REV_1_H__
5
6int diva_bri_init_card(diva_os_xdi_adapter_t * a);
7
8#endif
diff --git a/drivers/isdn/hardware/eicon/os_capi.h b/drivers/isdn/hardware/eicon/os_capi.h
new file mode 100644
index 000000000000..726f915a09e5
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/os_capi.h
@@ -0,0 +1,21 @@
1/* $Id: os_capi.h,v 1.7 2003/04/12 21:40:49 schindler Exp $
2 *
3 * ISDN interface module for Eicon active cards DIVA.
4 * CAPI Interface OS include files
5 *
6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 */
12
13#ifndef __OS_CAPI_H__
14#define __OS_CAPI_H__
15
16#include <linux/capi.h>
17#include <linux/kernelcapi.h>
18#include <linux/isdn/capiutil.h>
19#include <linux/isdn/capilli.h>
20
21#endif /* __OS_CAPI_H__ */
diff --git a/drivers/isdn/hardware/eicon/os_pri.c b/drivers/isdn/hardware/eicon/os_pri.c
new file mode 100644
index 000000000000..8ac207f75e54
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/os_pri.c
@@ -0,0 +1,1051 @@
1/* $Id: os_pri.c,v 1.32 2004/03/21 17:26:01 armin Exp $ */
2
3#include "platform.h"
4#include "debuglib.h"
5#include "cardtype.h"
6#include "pc.h"
7#include "pr_pc.h"
8#include "di_defs.h"
9#include "dsp_defs.h"
10#include "di.h"
11#include "io.h"
12
13#include "xdi_msg.h"
14#include "xdi_adapter.h"
15#include "os_pri.h"
16#include "diva_pci.h"
17#include "mi_pc.h"
18#include "pc_maint.h"
19#include "dsp_tst.h"
20#include "diva_dma.h"
21
22/* --------------------------------------------------------------------------
23 OS Dependent part of XDI driver for DIVA PRI Adapter
24
25 DSP detection/validation by Anthony Booth (Eicon Networks, www.eicon.com)
26-------------------------------------------------------------------------- */
27
28#define DIVA_PRI_NO_PCI_BIOS_WORKAROUND 1
29
30extern int diva_card_read_xlog(diva_os_xdi_adapter_t * a);
31
32/*
33** IMPORTS
34*/
35extern void prepare_pri_functions(PISDN_ADAPTER IoAdapter);
36extern void prepare_pri2_functions(PISDN_ADAPTER IoAdapter);
37extern void diva_xdi_display_adapter_features(int card);
38
39static int diva_pri_cleanup_adapter(diva_os_xdi_adapter_t * a);
40static int diva_pri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
41 diva_xdi_um_cfg_cmd_t * cmd, int length);
42static int pri_get_serial_number(diva_os_xdi_adapter_t * a);
43static int diva_pri_stop_adapter(diva_os_xdi_adapter_t * a);
44static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t * a);
45
46/*
47** Check card revision
48*/
49static int pri_is_rev_2_card(int card_ordinal)
50{
51 switch (card_ordinal) {
52 case CARDTYPE_DIVASRV_P_30M_V2_PCI:
53 case CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI:
54 return (1);
55 }
56 return (0);
57}
58
59static void diva_pri_set_addresses(diva_os_xdi_adapter_t * a)
60{
61 a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 0;
62 a->resources.pci.mem_type_id[MEM_TYPE_CONTROL] = 2;
63 a->resources.pci.mem_type_id[MEM_TYPE_CONFIG] = 4;
64 a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 0;
65 a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 2;
66 a->resources.pci.mem_type_id[MEM_TYPE_CFG] = 4;
67 a->resources.pci.mem_type_id[MEM_TYPE_PROM] = 3;
68
69 a->xdi_adapter.Address = a->resources.pci.addr[0];
70 a->xdi_adapter.Control = a->resources.pci.addr[2];
71 a->xdi_adapter.Config = a->resources.pci.addr[4];
72
73 a->xdi_adapter.ram = a->resources.pci.addr[0];
74 a->xdi_adapter.ram += MP_SHARED_RAM_OFFSET;
75
76 a->xdi_adapter.reset = a->resources.pci.addr[2];
77 a->xdi_adapter.reset += MP_RESET;
78
79 a->xdi_adapter.cfg = a->resources.pci.addr[4];
80 a->xdi_adapter.cfg += MP_IRQ_RESET;
81
82 a->xdi_adapter.sdram_bar = a->resources.pci.bar[0];
83
84 a->xdi_adapter.prom = a->resources.pci.addr[3];
85}
86
87/*
88** BAR0 - SDRAM, MP_MEMORY_SIZE, MP2_MEMORY_SIZE by Rev.2
89** BAR1 - DEVICES, 0x1000
90** BAR2 - CONTROL (REG), 0x2000
91** BAR3 - FLASH (REG), 0x8000
92** BAR4 - CONFIG (CFG), 0x1000
93*/
94int diva_pri_init_card(diva_os_xdi_adapter_t * a)
95{
96 int bar = 0;
97 int pri_rev_2;
98 unsigned long bar_length[5] = {
99 MP_MEMORY_SIZE,
100 0x1000,
101 0x2000,
102 0x8000,
103 0x1000
104 };
105
106 pri_rev_2 = pri_is_rev_2_card(a->CardOrdinal);
107
108 if (pri_rev_2) {
109 bar_length[0] = MP2_MEMORY_SIZE;
110 }
111 /*
112 Set properties
113 */
114 a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
115 DBG_LOG(("Load %s", a->xdi_adapter.Properties.Name))
116
117 /*
118 First initialization step: get and check hardware resoures.
119 Do not map resources and do not acecess card at this step
120 */
121 for (bar = 0; bar < 5; bar++) {
122 a->resources.pci.bar[bar] =
123 divasa_get_pci_bar(a->resources.pci.bus,
124 a->resources.pci.func, bar,
125 a->resources.pci.hdev);
126 if (!a->resources.pci.bar[bar]
127 || (a->resources.pci.bar[bar] == 0xFFFFFFF0)) {
128 DBG_ERR(("A: invalid bar[%d]=%08x", bar,
129 a->resources.pci.bar[bar]))
130 return (-1);
131 }
132 }
133 a->resources.pci.irq =
134 (byte) divasa_get_pci_irq(a->resources.pci.bus,
135 a->resources.pci.func,
136 a->resources.pci.hdev);
137 if (!a->resources.pci.irq) {
138 DBG_ERR(("A: invalid irq"));
139 return (-1);
140 }
141
142 /*
143 Map all BAR's
144 */
145 for (bar = 0; bar < 5; bar++) {
146 a->resources.pci.addr[bar] =
147 divasa_remap_pci_bar(a, bar, a->resources.pci.bar[bar],
148 bar_length[bar]);
149 if (!a->resources.pci.addr[bar]) {
150 DBG_ERR(("A: A(%d), can't map bar[%d]",
151 a->controller, bar))
152 diva_pri_cleanup_adapter(a);
153 return (-1);
154 }
155 }
156
157 /*
158 Set all memory areas
159 */
160 diva_pri_set_addresses(a);
161
162 /*
163 Get Serial Number of this adapter
164 */
165 if (pri_get_serial_number(a)) {
166 dword serNo;
167 serNo = a->resources.pci.bar[1] & 0xffff0000;
168 serNo |= ((dword) a->resources.pci.bus) << 8;
169 serNo += (a->resources.pci.func + a->controller + 1);
170 a->xdi_adapter.serialNo = serNo & ~0xFF000000;
171 DBG_ERR(("A: A(%d) can't get Serial Number, generated serNo=%ld",
172 a->controller, a->xdi_adapter.serialNo))
173 }
174
175
176 /*
177 Initialize os objects
178 */
179 if (diva_os_initialize_spin_lock(&a->xdi_adapter.isr_spin_lock, "isr")) {
180 diva_pri_cleanup_adapter(a);
181 return (-1);
182 }
183 if (diva_os_initialize_spin_lock
184 (&a->xdi_adapter.data_spin_lock, "data")) {
185 diva_pri_cleanup_adapter(a);
186 return (-1);
187 }
188
189 strcpy(a->xdi_adapter.req_soft_isr.dpc_thread_name, "kdivasprid");
190
191 if (diva_os_initialize_soft_isr(&a->xdi_adapter.req_soft_isr,
192 DIDpcRoutine, &a->xdi_adapter)) {
193 diva_pri_cleanup_adapter(a);
194 return (-1);
195 }
196
197 /*
198 Do not initialize second DPC - only one thread will be created
199 */
200 a->xdi_adapter.isr_soft_isr.object =
201 a->xdi_adapter.req_soft_isr.object;
202
203 /*
204 Next step of card initialization:
205 set up all interface pointers
206 */
207 a->xdi_adapter.Channels = CardProperties[a->CardOrdinal].Channels;
208 a->xdi_adapter.e_max = CardProperties[a->CardOrdinal].E_info;
209
210 a->xdi_adapter.e_tbl =
211 diva_os_malloc(0, a->xdi_adapter.e_max * sizeof(E_INFO));
212 if (!a->xdi_adapter.e_tbl) {
213 diva_pri_cleanup_adapter(a);
214 return (-1);
215 }
216 memset(a->xdi_adapter.e_tbl, 0x00, a->xdi_adapter.e_max * sizeof(E_INFO));
217
218 a->xdi_adapter.a.io = &a->xdi_adapter;
219 a->xdi_adapter.DIRequest = request;
220 a->interface.cleanup_adapter_proc = diva_pri_cleanup_adapter;
221 a->interface.cmd_proc = diva_pri_cmd_card_proc;
222
223 if (pri_rev_2) {
224 prepare_pri2_functions(&a->xdi_adapter);
225 } else {
226 prepare_pri_functions(&a->xdi_adapter);
227 }
228
229 a->dsp_mask = diva_pri_detect_dsps(a);
230
231 /*
232 Allocate DMA map
233 */
234 if (pri_rev_2) {
235 diva_init_dma_map(a->resources.pci.hdev,
236 (struct _diva_dma_map_entry **) &a->xdi_adapter.dma_map, 32);
237 }
238
239 /*
240 Set IRQ handler
241 */
242 a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq;
243 sprintf(a->xdi_adapter.irq_info.irq_name,
244 "DIVA PRI %ld", (long) a->xdi_adapter.serialNo);
245
246 if (diva_os_register_irq(a, a->xdi_adapter.irq_info.irq_nr,
247 a->xdi_adapter.irq_info.irq_name)) {
248 diva_pri_cleanup_adapter(a);
249 return (-1);
250 }
251 a->xdi_adapter.irq_info.registered = 1;
252
253 diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
254 a->resources.pci.irq, a->xdi_adapter.serialNo);
255
256 return (0);
257}
258
259static int diva_pri_cleanup_adapter(diva_os_xdi_adapter_t * a)
260{
261 int bar = 0;
262
263 /*
264 Stop Adapter if adapter is running
265 */
266 if (a->xdi_adapter.Initialized) {
267 diva_pri_stop_adapter(a);
268 }
269
270 /*
271 Remove ISR Handler
272 */
273 if (a->xdi_adapter.irq_info.registered) {
274 diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr);
275 }
276 a->xdi_adapter.irq_info.registered = 0;
277
278 /*
279 Step 1: unmap all BAR's, if any was mapped
280 */
281 for (bar = 0; bar < 5; bar++) {
282 if (a->resources.pci.bar[bar]
283 && a->resources.pci.addr[bar]) {
284 divasa_unmap_pci_bar(a->resources.pci.addr[bar]);
285 a->resources.pci.bar[bar] = 0;
286 a->resources.pci.addr[bar] = NULL;
287 }
288 }
289
290 /*
291 Free OS objects
292 */
293 diva_os_cancel_soft_isr(&a->xdi_adapter.isr_soft_isr);
294 diva_os_cancel_soft_isr(&a->xdi_adapter.req_soft_isr);
295
296 diva_os_remove_soft_isr(&a->xdi_adapter.req_soft_isr);
297 a->xdi_adapter.isr_soft_isr.object = NULL;
298
299 diva_os_destroy_spin_lock(&a->xdi_adapter.isr_spin_lock, "rm");
300 diva_os_destroy_spin_lock(&a->xdi_adapter.data_spin_lock, "rm");
301
302 /*
303 Free memory accupied by XDI adapter
304 */
305 if (a->xdi_adapter.e_tbl) {
306 diva_os_free(0, a->xdi_adapter.e_tbl);
307 a->xdi_adapter.e_tbl = NULL;
308 }
309 a->xdi_adapter.Channels = 0;
310 a->xdi_adapter.e_max = 0;
311
312
313 /*
314 Free adapter DMA map
315 */
316 diva_free_dma_map(a->resources.pci.hdev,
317 (struct _diva_dma_map_entry *) a->xdi_adapter.
318 dma_map);
319 a->xdi_adapter.dma_map = NULL;
320
321
322 /*
323 Detach this adapter from debug driver
324 */
325
326 return (0);
327}
328
329/*
330** Activate On Board Boot Loader
331*/
332static int diva_pri_reset_adapter(PISDN_ADAPTER IoAdapter)
333{
334 dword i;
335 struct mp_load __iomem *boot;
336
337 if (!IoAdapter->Address || !IoAdapter->reset) {
338 return (-1);
339 }
340 if (IoAdapter->Initialized) {
341 DBG_ERR(("A: A(%d) can't reset PRI adapter - please stop first",
342 IoAdapter->ANum))
343 return (-1);
344 }
345
346 boot = (struct mp_load __iomem *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
347 WRITE_DWORD(&boot->err, 0);
348 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
349
350 IoAdapter->rstFnc(IoAdapter);
351
352 diva_os_wait(10);
353
354 boot = (struct mp_load __iomem *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
355 i = READ_DWORD(&boot->live);
356
357 diva_os_wait(10);
358 if (i == READ_DWORD(&boot->live)) {
359 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
360 DBG_ERR(("A: A(%d) CPU on PRI %ld is not alive!",
361 IoAdapter->ANum, IoAdapter->serialNo))
362 return (-1);
363 }
364 if (READ_DWORD(&boot->err)) {
365 DBG_ERR(("A: A(%d) PRI %ld Board Selftest failed, error=%08lx",
366 IoAdapter->ANum, IoAdapter->serialNo,
367 READ_DWORD(&boot->err)))
368 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
369 return (-1);
370 }
371 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
372
373 /*
374 Forget all outstanding entities
375 */
376 IoAdapter->e_count = 0;
377 if (IoAdapter->e_tbl) {
378 memset(IoAdapter->e_tbl, 0x00,
379 IoAdapter->e_max * sizeof(E_INFO));
380 }
381 IoAdapter->head = 0;
382 IoAdapter->tail = 0;
383 IoAdapter->assign = 0;
384 IoAdapter->trapped = 0;
385
386 memset(&IoAdapter->a.IdTable[0], 0x00,
387 sizeof(IoAdapter->a.IdTable));
388 memset(&IoAdapter->a.IdTypeTable[0], 0x00,
389 sizeof(IoAdapter->a.IdTypeTable));
390 memset(&IoAdapter->a.FlowControlIdTable[0], 0x00,
391 sizeof(IoAdapter->a.FlowControlIdTable));
392 memset(&IoAdapter->a.FlowControlSkipTable[0], 0x00,
393 sizeof(IoAdapter->a.FlowControlSkipTable));
394 memset(&IoAdapter->a.misc_flags_table[0], 0x00,
395 sizeof(IoAdapter->a.misc_flags_table));
396 memset(&IoAdapter->a.rx_stream[0], 0x00,
397 sizeof(IoAdapter->a.rx_stream));
398 memset(&IoAdapter->a.tx_stream[0], 0x00,
399 sizeof(IoAdapter->a.tx_stream));
400 memset(&IoAdapter->a.tx_pos[0], 0x00, sizeof(IoAdapter->a.tx_pos));
401 memset(&IoAdapter->a.rx_pos[0], 0x00, sizeof(IoAdapter->a.rx_pos));
402
403 return (0);
404}
405
406static int
407diva_pri_write_sdram_block(PISDN_ADAPTER IoAdapter,
408 dword address,
409 const byte * data, dword length, dword limit)
410{
411 byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
412 byte __iomem *mem = p;
413
414 if (((address + length) >= limit) || !mem) {
415 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
416 DBG_ERR(("A: A(%d) write PRI address=0x%08lx",
417 IoAdapter->ANum, address + length))
418 return (-1);
419 }
420 mem += address;
421
422 /* memcpy_toio(), maybe? */
423 while (length--) {
424 WRITE_BYTE(mem++, *data++);
425 }
426
427 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
428 return (0);
429}
430
431static int
432diva_pri_start_adapter(PISDN_ADAPTER IoAdapter,
433 dword start_address, dword features)
434{
435 dword i;
436 int started = 0;
437 byte __iomem *p;
438 struct mp_load __iomem *boot = (struct mp_load __iomem *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
439 ADAPTER *a = &IoAdapter->a;
440
441 if (IoAdapter->Initialized) {
442 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
443 DBG_ERR(("A: A(%d) pri_start_adapter, adapter already running",
444 IoAdapter->ANum))
445 return (-1);
446 }
447 if (!boot) {
448 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
449 DBG_ERR(("A: PRI %ld can't start, adapter not mapped",
450 IoAdapter->serialNo))
451 return (-1);
452 }
453
454 sprintf(IoAdapter->Name, "A(%d)", (int) IoAdapter->ANum);
455 DBG_LOG(("A(%d) start PRI at 0x%08lx", IoAdapter->ANum,
456 start_address))
457
458 WRITE_DWORD(&boot->addr, start_address);
459 WRITE_DWORD(&boot->cmd, 3);
460
461 for (i = 0; i < 300; ++i) {
462 diva_os_wait(10);
463 if ((READ_DWORD(&boot->signature) >> 16) == 0x4447) {
464 DBG_LOG(("A(%d) Protocol startup time %d.%02d seconds",
465 IoAdapter->ANum, (i / 100), (i % 100)))
466 started = 1;
467 break;
468 }
469 }
470
471 if (!started) {
472 byte __iomem *p = (byte __iomem *)boot;
473 dword TrapId;
474 dword debug;
475 TrapId = READ_DWORD(&p[0x80]);
476 debug = READ_DWORD(&p[0x1c]);
477 DBG_ERR(("A(%d) Adapter start failed 0x%08lx, TrapId=%08lx, debug=%08lx",
478 IoAdapter->ANum, READ_DWORD(&boot->signature),
479 TrapId, debug))
480 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
481 if (IoAdapter->trapFnc) {
482 (*(IoAdapter->trapFnc)) (IoAdapter);
483 }
484 IoAdapter->stop(IoAdapter);
485 return (-1);
486 }
487 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
488
489 IoAdapter->Initialized = TRUE;
490
491 /*
492 Check Interrupt
493 */
494 IoAdapter->IrqCount = 0;
495 p = DIVA_OS_MEM_ATTACH_CFG(IoAdapter);
496 WRITE_DWORD(p, (dword) ~ 0x03E00000);
497 DIVA_OS_MEM_DETACH_CFG(IoAdapter, p);
498 a->ReadyInt = 1;
499 a->ram_out(a, &PR_RAM->ReadyInt, 1);
500
501 for (i = 100; !IoAdapter->IrqCount && (i-- > 0); diva_os_wait(10));
502
503 if (!IoAdapter->IrqCount) {
504 DBG_ERR(("A: A(%d) interrupt test failed",
505 IoAdapter->ANum))
506 IoAdapter->Initialized = FALSE;
507 IoAdapter->stop(IoAdapter);
508 return (-1);
509 }
510
511 IoAdapter->Properties.Features = (word) features;
512
513 diva_xdi_display_adapter_features(IoAdapter->ANum);
514
515 DBG_LOG(("A(%d) PRI adapter successfull started", IoAdapter->ANum))
516 /*
517 Register with DIDD
518 */
519 diva_xdi_didd_register_adapter(IoAdapter->ANum);
520
521 return (0);
522}
523
524static void diva_pri_clear_interrupts(diva_os_xdi_adapter_t * a)
525{
526 PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
527
528 /*
529 clear any pending interrupt
530 */
531 IoAdapter->disIrq(IoAdapter);
532
533 IoAdapter->tst_irq(&IoAdapter->a);
534 IoAdapter->clr_irq(&IoAdapter->a);
535 IoAdapter->tst_irq(&IoAdapter->a);
536
537 /*
538 kill pending dpcs
539 */
540 diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
541 diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
542}
543
544/*
545** Stop Adapter, but do not unmap/unregister - adapter
546** will be restarted later
547*/
548static int diva_pri_stop_adapter(diva_os_xdi_adapter_t * a)
549{
550 PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
551 int i = 100;
552
553 if (!IoAdapter->ram) {
554 return (-1);
555 }
556 if (!IoAdapter->Initialized) {
557 DBG_ERR(("A: A(%d) can't stop PRI adapter - not running",
558 IoAdapter->ANum))
559 return (-1); /* nothing to stop */
560 }
561 IoAdapter->Initialized = 0;
562
563 /*
564 Disconnect Adapter from DIDD
565 */
566 diva_xdi_didd_remove_adapter(IoAdapter->ANum);
567
568 /*
569 Stop interrupts
570 */
571 a->clear_interrupts_proc = diva_pri_clear_interrupts;
572 IoAdapter->a.ReadyInt = 1;
573 IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt);
574 do {
575 diva_os_sleep(10);
576 } while (i-- && a->clear_interrupts_proc);
577
578 if (a->clear_interrupts_proc) {
579 diva_pri_clear_interrupts(a);
580 a->clear_interrupts_proc = NULL;
581 DBG_ERR(("A: A(%d) no final interrupt from PRI adapter",
582 IoAdapter->ANum))
583 }
584 IoAdapter->a.ReadyInt = 0;
585
586 /*
587 Stop and reset adapter
588 */
589 IoAdapter->stop(IoAdapter);
590
591 return (0);
592}
593
594/*
595** Process commands form configuration/download framework and from
596** user mode
597**
598** return 0 on success
599*/
600static int
601diva_pri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
602 diva_xdi_um_cfg_cmd_t * cmd, int length)
603{
604 int ret = -1;
605
606 if (cmd->adapter != a->controller) {
607 DBG_ERR(("A: pri_cmd, invalid controller=%d != %d",
608 cmd->adapter, a->controller))
609 return (-1);
610 }
611
612 switch (cmd->command) {
613 case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL:
614 a->xdi_mbox.data_length = sizeof(dword);
615 a->xdi_mbox.data =
616 diva_os_malloc(0, a->xdi_mbox.data_length);
617 if (a->xdi_mbox.data) {
618 *(dword *) a->xdi_mbox.data =
619 (dword) a->CardOrdinal;
620 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
621 ret = 0;
622 }
623 break;
624
625 case DIVA_XDI_UM_CMD_GET_SERIAL_NR:
626 a->xdi_mbox.data_length = sizeof(dword);
627 a->xdi_mbox.data =
628 diva_os_malloc(0, a->xdi_mbox.data_length);
629 if (a->xdi_mbox.data) {
630 *(dword *) a->xdi_mbox.data =
631 (dword) a->xdi_adapter.serialNo;
632 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
633 ret = 0;
634 }
635 break;
636
637 case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
638 a->xdi_mbox.data_length = sizeof(dword) * 9;
639 a->xdi_mbox.data =
640 diva_os_malloc(0, a->xdi_mbox.data_length);
641 if (a->xdi_mbox.data) {
642 int i;
643 dword *data = (dword *) a->xdi_mbox.data;
644
645 for (i = 0; i < 8; i++) {
646 *data++ = a->resources.pci.bar[i];
647 }
648 *data++ = (dword) a->resources.pci.irq;
649 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
650 ret = 0;
651 }
652 break;
653
654 case DIVA_XDI_UM_CMD_RESET_ADAPTER:
655 ret = diva_pri_reset_adapter(&a->xdi_adapter);
656 break;
657
658 case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK:
659 ret = diva_pri_write_sdram_block(&a->xdi_adapter,
660 cmd->command_data.
661 write_sdram.offset,
662 (byte *) & cmd[1],
663 cmd->command_data.
664 write_sdram.length,
665 pri_is_rev_2_card(a->
666 CardOrdinal)
667 ? MP2_MEMORY_SIZE :
668 MP_MEMORY_SIZE);
669 break;
670
671 case DIVA_XDI_UM_CMD_STOP_ADAPTER:
672 ret = diva_pri_stop_adapter(a);
673 break;
674
675 case DIVA_XDI_UM_CMD_START_ADAPTER:
676 ret = diva_pri_start_adapter(&a->xdi_adapter,
677 cmd->command_data.start.
678 offset,
679 cmd->command_data.start.
680 features);
681 break;
682
683 case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES:
684 a->xdi_adapter.features =
685 cmd->command_data.features.features;
686 a->xdi_adapter.a.protocol_capabilities =
687 a->xdi_adapter.features;
688 DBG_TRC(("Set raw protocol features (%08x)",
689 a->xdi_adapter.features))
690 ret = 0;
691 break;
692
693 case DIVA_XDI_UM_CMD_GET_CARD_STATE:
694 a->xdi_mbox.data_length = sizeof(dword);
695 a->xdi_mbox.data =
696 diva_os_malloc(0, a->xdi_mbox.data_length);
697 if (a->xdi_mbox.data) {
698 dword *data = (dword *) a->xdi_mbox.data;
699 if (!a->xdi_adapter.ram ||
700 !a->xdi_adapter.reset ||
701 !a->xdi_adapter.cfg) {
702 *data = 3;
703 } else if (a->xdi_adapter.trapped) {
704 *data = 2;
705 } else if (a->xdi_adapter.Initialized) {
706 *data = 1;
707 } else {
708 *data = 0;
709 }
710 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
711 ret = 0;
712 }
713 break;
714
715 case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
716 ret = diva_card_read_xlog(a);
717 break;
718
719 case DIVA_XDI_UM_CMD_READ_SDRAM:
720 if (a->xdi_adapter.Address) {
721 if (
722 (a->xdi_mbox.data_length =
723 cmd->command_data.read_sdram.length)) {
724 if (
725 (a->xdi_mbox.data_length +
726 cmd->command_data.read_sdram.offset) <
727 a->xdi_adapter.MemorySize) {
728 a->xdi_mbox.data =
729 diva_os_malloc(0,
730 a->xdi_mbox.
731 data_length);
732 if (a->xdi_mbox.data) {
733 byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(&a->xdi_adapter);
734 byte __iomem *src = p;
735 byte *dst = a->xdi_mbox.data;
736 dword len = a->xdi_mbox.data_length;
737
738 src += cmd->command_data.read_sdram.offset;
739
740 while (len--) {
741 *dst++ = READ_BYTE(src++);
742 }
743 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
744 DIVA_OS_MEM_DETACH_ADDRESS(&a->xdi_adapter, p);
745 ret = 0;
746 }
747 }
748 }
749 }
750 break;
751
752 default:
753 DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller,
754 cmd->command))
755 }
756
757 return (ret);
758}
759
760/*
761** Get Serial Number
762*/
763static int pri_get_serial_number(diva_os_xdi_adapter_t * a)
764{
765 byte data[64];
766 int i;
767 dword len = sizeof(data);
768 volatile byte __iomem *config;
769 volatile byte __iomem *flash;
770 byte c;
771
772/*
773 * First set some GT6401x config registers before accessing the BOOT-ROM
774 */
775 config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter);
776 c = READ_BYTE(&config[0xc3c]);
777 if (!(c & 0x08)) {
778 WRITE_BYTE(&config[0xc3c], c); /* Base Address enable register */
779 }
780 WRITE_BYTE(&config[LOW_BOOTCS_DREG], 0x00);
781 WRITE_BYTE(&config[HI_BOOTCS_DREG], 0xFF);
782 DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config);
783/*
784 * Read only the last 64 bytes of manufacturing data
785 */
786 memset(data, '\0', len);
787 flash = DIVA_OS_MEM_ATTACH_PROM(&a->xdi_adapter);
788 for (i = 0; i < len; i++) {
789 data[i] = READ_BYTE(&flash[0x8000 - len + i]);
790 }
791 DIVA_OS_MEM_DETACH_PROM(&a->xdi_adapter, flash);
792
793 config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter);
794 WRITE_BYTE(&config[LOW_BOOTCS_DREG], 0xFC); /* Disable FLASH EPROM access */
795 WRITE_BYTE(&config[HI_BOOTCS_DREG], 0xFF);
796 DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config);
797
798 if (memcmp(&data[48], "DIVAserverPR", 12)) {
799#if !defined(DIVA_PRI_NO_PCI_BIOS_WORKAROUND) /* { */
800 word cmd = 0, cmd_org;
801 void *addr;
802 dword addr1, addr3, addr4;
803 byte Bus, Slot;
804 void *hdev;
805 addr4 = a->resources.pci.bar[4];
806 addr3 = a->resources.pci.bar[3]; /* flash */
807 addr1 = a->resources.pci.bar[1]; /* unused */
808
809 DBG_ERR(("A: apply Compaq BIOS workaround"))
810 DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
811 data[0], data[1], data[2], data[3],
812 data[4], data[5], data[6], data[7]))
813
814 Bus = a->resources.pci.bus;
815 Slot = a->resources.pci.func;
816 hdev = a->resources.pci.hdev;
817 PCIread(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
818 PCIwrite(Bus, Slot, 0x04, &cmd, sizeof(cmd), hdev);
819
820 PCIwrite(Bus, Slot, 0x14, &addr4, sizeof(addr4), hdev);
821 PCIwrite(Bus, Slot, 0x20, &addr1, sizeof(addr1), hdev);
822
823 PCIwrite(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
824
825 addr = a->resources.pci.addr[1];
826 a->resources.pci.addr[1] = a->resources.pci.addr[4];
827 a->resources.pci.addr[4] = addr;
828
829 addr1 = a->resources.pci.bar[1];
830 a->resources.pci.bar[1] = a->resources.pci.bar[4];
831 a->resources.pci.bar[4] = addr1;
832
833 /*
834 Try to read Flash again
835 */
836 len = sizeof(data);
837
838 config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter);
839 if (!(config[0xc3c] & 0x08)) {
840 config[0xc3c] |= 0x08; /* Base Address enable register */
841 }
842 config[LOW_BOOTCS_DREG] = 0x00;
843 config[HI_BOOTCS_DREG] = 0xFF;
844 DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config);
845
846 memset(data, '\0', len);
847 flash = DIVA_OS_MEM_ATTACH_PROM(&a->xdi_adapter);
848 for (i = 0; i < len; i++) {
849 data[i] = flash[0x8000 - len + i];
850 }
851 DIVA_OS_MEM_ATTACH_PROM(&a->xdi_adapter, flash);
852 config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter);
853 config[LOW_BOOTCS_DREG] = 0xFC;
854 config[HI_BOOTCS_DREG] = 0xFF;
855 DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config);
856
857 if (memcmp(&data[48], "DIVAserverPR", 12)) {
858 DBG_ERR(("A: failed to read serial number"))
859 DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
860 data[0], data[1], data[2], data[3],
861 data[4], data[5], data[6], data[7]))
862 return (-1);
863 }
864#else /* } { */
865 DBG_ERR(("A: failed to read DIVA signature word"))
866 DBG_LOG(("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
867 data[0], data[1], data[2], data[3],
868 data[4], data[5], data[6], data[7]))
869 DBG_LOG(("%02x:%02x:%02x:%02x", data[47], data[46],
870 data[45], data[44]))
871#endif /* } */
872 }
873
874 a->xdi_adapter.serialNo =
875 (data[47] << 24) | (data[46] << 16) | (data[45] << 8) |
876 data[44];
877 if (!a->xdi_adapter.serialNo
878 || (a->xdi_adapter.serialNo == 0xffffffff)) {
879 a->xdi_adapter.serialNo = 0;
880 DBG_ERR(("A: failed to read serial number"))
881 return (-1);
882 }
883
884 DBG_LOG(("Serial No. : %ld", a->xdi_adapter.serialNo))
885 DBG_TRC(("Board Revision : %d.%02d", (int) data[41],
886 (int) data[40]))
887 DBG_TRC(("PLD revision : %d.%02d", (int) data[33],
888 (int) data[32]))
889 DBG_TRC(("Boot loader version : %d.%02d", (int) data[37],
890 (int) data[36]))
891
892 DBG_TRC(("Manufacturing Date : %d/%02d/%02d (yyyy/mm/dd)",
893 (int) ((data[28] > 90) ? 1900 : 2000) +
894 (int) data[28], (int) data[29], (int) data[30]))
895
896 return (0);
897}
898
899void diva_os_prepare_pri2_functions(PISDN_ADAPTER IoAdapter)
900{
901}
902
903void diva_os_prepare_pri_functions(PISDN_ADAPTER IoAdapter)
904{
905}
906
907/*
908** Checks presence of DSP on board
909*/
910static int
911dsp_check_presence(volatile byte __iomem * addr, volatile byte __iomem * data, int dsp)
912{
913 word pattern;
914
915 WRITE_WORD(addr, 0x4000);
916 WRITE_WORD(data, DSP_SIGNATURE_PROBE_WORD);
917
918 WRITE_WORD(addr, 0x4000);
919 pattern = READ_WORD(data);
920
921 if (pattern != DSP_SIGNATURE_PROBE_WORD) {
922 DBG_TRC(("W: DSP[%d] %04x(is) != %04x(should)",
923 dsp, pattern, DSP_SIGNATURE_PROBE_WORD))
924 return (-1);
925 }
926
927 WRITE_WORD(addr, 0x4000);
928 WRITE_WORD(data, ~DSP_SIGNATURE_PROBE_WORD);
929
930 WRITE_WORD(addr, 0x4000);
931 pattern = READ_WORD(data);
932
933 if (pattern != (word) ~ DSP_SIGNATURE_PROBE_WORD) {
934 DBG_ERR(("A: DSP[%d] %04x(is) != %04x(should)",
935 dsp, pattern, (word) ~ DSP_SIGNATURE_PROBE_WORD))
936 return (-2);
937 }
938
939 DBG_TRC(("DSP[%d] present", dsp))
940
941 return (0);
942}
943
944
945/*
946** Check if DSP's are present and operating
947** Information about detected DSP's is returned as bit mask
948** Bit 0 - DSP1
949** ...
950** ...
951** ...
952** Bit 29 - DSP30
953*/
954static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t * a)
955{
956 byte __iomem *base;
957 byte __iomem *p;
958 dword ret = 0;
959 dword row_offset[7] = {
960 0x00000000,
961 0x00000800, /* 1 - ROW 1 */
962 0x00000840, /* 2 - ROW 2 */
963 0x00001000, /* 3 - ROW 3 */
964 0x00001040, /* 4 - ROW 4 */
965 0x00000000 /* 5 - ROW 0 */
966 };
967
968 byte __iomem *dsp_addr_port;
969 byte __iomem *dsp_data_port;
970 byte row_state;
971 int dsp_row = 0, dsp_index, dsp_num;
972
973 if (!a->xdi_adapter.Control || !a->xdi_adapter.reset) {
974 return (0);
975 }
976
977 p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter);
978 WRITE_BYTE(p, _MP_RISC_RESET | _MP_DSP_RESET);
979 DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p);
980 diva_os_wait(5);
981
982 base = DIVA_OS_MEM_ATTACH_CONTROL(&a->xdi_adapter);
983
984 for (dsp_num = 0; dsp_num < 30; dsp_num++) {
985 dsp_row = dsp_num / 7 + 1;
986 dsp_index = dsp_num % 7;
987
988 dsp_data_port = base;
989 dsp_addr_port = base;
990
991 dsp_data_port += row_offset[dsp_row];
992 dsp_addr_port += row_offset[dsp_row];
993
994 dsp_data_port += (dsp_index * 8);
995 dsp_addr_port += (dsp_index * 8) + 0x80;
996
997 if (!dsp_check_presence
998 (dsp_addr_port, dsp_data_port, dsp_num + 1)) {
999 ret |= (1 << dsp_num);
1000 }
1001 }
1002 DIVA_OS_MEM_DETACH_CONTROL(&a->xdi_adapter, base);
1003
1004 p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter);
1005 WRITE_BYTE(p, _MP_RISC_RESET | _MP_LED1 | _MP_LED2);
1006 DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p);
1007 diva_os_wait(5);
1008
1009 /*
1010 Verify modules
1011 */
1012 for (dsp_row = 0; dsp_row < 4; dsp_row++) {
1013 row_state = ((ret >> (dsp_row * 7)) & 0x7F);
1014 if (row_state && (row_state != 0x7F)) {
1015 for (dsp_index = 0; dsp_index < 7; dsp_index++) {
1016 if (!(row_state & (1 << dsp_index))) {
1017 DBG_ERR(("A: MODULE[%d]-DSP[%d] failed",
1018 dsp_row + 1,
1019 dsp_index + 1))
1020 }
1021 }
1022 }
1023 }
1024
1025 if (!(ret & 0x10000000)) {
1026 DBG_ERR(("A: ON BOARD-DSP[1] failed"))
1027 }
1028 if (!(ret & 0x20000000)) {
1029 DBG_ERR(("A: ON BOARD-DSP[2] failed"))
1030 }
1031
1032 /*
1033 Print module population now
1034 */
1035 DBG_LOG(("+-----------------------+"))
1036 DBG_LOG(("| DSP MODULE POPULATION |"))
1037 DBG_LOG(("+-----------------------+"))
1038 DBG_LOG(("| 1 | 2 | 3 | 4 |"))
1039 DBG_LOG(("+-----------------------+"))
1040 DBG_LOG(("| %s | %s | %s | %s |",
1041 ((ret >> (0 * 7)) & 0x7F) ? "Y" : "N",
1042 ((ret >> (1 * 7)) & 0x7F) ? "Y" : "N",
1043 ((ret >> (2 * 7)) & 0x7F) ? "Y" : "N",
1044 ((ret >> (3 * 7)) & 0x7F) ? "Y" : "N"))
1045 DBG_LOG(("+-----------------------+"))
1046
1047 DBG_LOG(("DSP's(present-absent):%08x-%08x", ret,
1048 ~ret & 0x3fffffff))
1049
1050 return (ret);
1051}
diff --git a/drivers/isdn/hardware/eicon/os_pri.h b/drivers/isdn/hardware/eicon/os_pri.h
new file mode 100644
index 000000000000..a7c42f94d78a
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/os_pri.h
@@ -0,0 +1,8 @@
1/* $Id: os_pri.h,v 1.1.2.2 2001/02/08 12:25:44 armin Exp $ */
2
3#ifndef __DIVA_OS_PRI_REV_1_H__
4#define __DIVA_OS_PRI_REV_1_H__
5
6int diva_pri_init_card(diva_os_xdi_adapter_t * a);
7
8#endif
diff --git a/drivers/isdn/hardware/eicon/pc.h b/drivers/isdn/hardware/eicon/pc.h
new file mode 100644
index 000000000000..1c6945768a35
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/pc.h
@@ -0,0 +1,738 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef PC_H_INCLUDED /* { */
27#define PC_H_INCLUDED
28/*------------------------------------------------------------------*/
29/* buffer definition */
30/*------------------------------------------------------------------*/
31typedef struct {
32 word length; /* length of data/parameter field */
33 byte P[270]; /* data/parameter field */
34} PBUFFER;
35/*------------------------------------------------------------------*/
36/* dual port ram structure */
37/*------------------------------------------------------------------*/
38struct dual
39{
40 byte Req; /* request register */
41 byte ReqId; /* request task/entity identification */
42 byte Rc; /* return code register */
43 byte RcId; /* return code task/entity identification */
44 byte Ind; /* Indication register */
45 byte IndId; /* Indication task/entity identification */
46 byte IMask; /* Interrupt Mask Flag */
47 byte RNR; /* Receiver Not Ready (set by PC) */
48 byte XLock; /* XBuffer locked Flag */
49 byte Int; /* ISDN-S interrupt */
50 byte ReqCh; /* Channel field for layer-3 Requests */
51 byte RcCh; /* Channel field for layer-3 Returncodes */
52 byte IndCh; /* Channel field for layer-3 Indications */
53 byte MInd; /* more data indication field */
54 word MLength; /* more data total packet length */
55 byte ReadyInt; /* request field for ready interrupt */
56 byte SWReg; /* Software register for special purposes */
57 byte Reserved[11]; /* reserved space */
58 byte InterfaceType; /* interface type 1=16K interface */
59 word Signature; /* ISDN-S adapter Signature (GD) */
60 PBUFFER XBuffer; /* Transmit Buffer */
61 PBUFFER RBuffer; /* Receive Buffer */
62};
63/*------------------------------------------------------------------*/
64/* SWReg Values (0 means no command) */
65/*------------------------------------------------------------------*/
66#define SWREG_DIE_WITH_LEDON 0x01
67#define SWREG_HALT_CPU 0x02 /* Push CPU into a while(1) loop */
68/*------------------------------------------------------------------*/
69/* Id Fields Coding */
70/*------------------------------------------------------------------*/
71#define ID_MASK 0xe0 /* Mask for the ID field */
72#define GL_ERR_ID 0x1f /* ID for error reporting on global requests*/
73#define DSIG_ID 0x00 /* ID for D-channel signaling */
74#define NL_ID 0x20 /* ID for network-layer access (B or D) */
75#define BLLC_ID 0x60 /* ID for B-channel link level access */
76#define TASK_ID 0x80 /* ID for dynamic user tasks */
77#define TIMER_ID 0xa0 /* ID for timer task */
78#define TEL_ID 0xc0 /* ID for telephone support */
79#define MAN_ID 0xe0 /* ID for management */
80/*------------------------------------------------------------------*/
81/* ASSIGN and REMOVE requests are the same for all entities */
82/*------------------------------------------------------------------*/
83#define ASSIGN 0x01
84#define UREMOVE 0xfe /* without return code */
85#define REMOVE 0xff
86/*------------------------------------------------------------------*/
87/* Timer Interrupt Task Interface */
88/*------------------------------------------------------------------*/
89#define ASSIGN_TIM 0x01
90#define REMOVE_TIM 0xff
91/*------------------------------------------------------------------*/
92/* dynamic user task interface */
93/*------------------------------------------------------------------*/
94#define ASSIGN_TSK 0x01
95#define REMOVE_TSK 0xff
96#define LOAD 0xf0
97#define RELOCATE 0xf1
98#define START 0xf2
99#define LOAD2 0xf3
100#define RELOCATE2 0xf4
101/*------------------------------------------------------------------*/
102/* dynamic user task messages */
103/*------------------------------------------------------------------*/
104#define TSK_B2 0x0000
105#define TSK_WAKEUP 0x2000
106#define TSK_TIMER 0x4000
107#define TSK_TSK 0x6000
108#define TSK_PC 0xe000
109/*------------------------------------------------------------------*/
110/* LL management primitives */
111/*------------------------------------------------------------------*/
112#define ASSIGN_LL 1 /* assign logical link */
113#define REMOVE_LL 0xff /* remove logical link */
114/*------------------------------------------------------------------*/
115/* LL service primitives */
116/*------------------------------------------------------------------*/
117#define LL_UDATA 1 /* link unit data request/indication */
118#define LL_ESTABLISH 2 /* link establish request/indication */
119#define LL_RELEASE 3 /* link release request/indication */
120#define LL_DATA 4 /* data request/indication */
121#define LL_LOCAL 5 /* switch to local operation (COM only) */
122#define LL_DATA_PEND 5 /* data pending indication (SDLC SHM only) */
123#define LL_REMOTE 6 /* switch to remote operation (COM only) */
124#define LL_TEST 8 /* link test request */
125#define LL_MDATA 9 /* more data request/indication */
126#define LL_BUDATA 10 /* broadcast unit data request/indication */
127#define LL_XID 12 /* XID command request/indication */
128#define LL_XID_R 13 /* XID response request/indication */
129/*------------------------------------------------------------------*/
130/* NL service primitives */
131/*------------------------------------------------------------------*/
132#define N_MDATA 1 /* more data to come REQ/IND */
133#define N_CONNECT 2 /* OSI N-CONNECT REQ/IND */
134#define N_CONNECT_ACK 3 /* OSI N-CONNECT CON/RES */
135#define N_DISC 4 /* OSI N-DISC REQ/IND */
136#define N_DISC_ACK 5 /* OSI N-DISC CON/RES */
137#define N_RESET 6 /* OSI N-RESET REQ/IND */
138#define N_RESET_ACK 7 /* OSI N-RESET CON/RES */
139#define N_DATA 8 /* OSI N-DATA REQ/IND */
140#define N_EDATA 9 /* OSI N-EXPEDITED DATA REQ/IND */
141#define N_UDATA 10 /* OSI D-UNIT-DATA REQ/IND */
142#define N_BDATA 11 /* BROADCAST-DATA REQ/IND */
143#define N_DATA_ACK 12 /* data ack ind for D-bit procedure */
144#define N_EDATA_ACK 13 /* data ack ind for INTERRUPT */
145#define N_XON 15 /* clear RNR state */
146#define N_COMBI_IND N_XON /* combined indication */
147#define N_Q_BIT 0x10 /* Q-bit for req/ind */
148#define N_M_BIT 0x20 /* M-bit for req/ind */
149#define N_D_BIT 0x40 /* D-bit for req/ind */
150/*------------------------------------------------------------------*/
151/* Signaling management primitives */
152/*------------------------------------------------------------------*/
153#define ASSIGN_SIG 1 /* assign signaling task */
154#define UREMOVE_SIG 0xfe /* remove signaling task without return code*/
155#define REMOVE_SIG 0xff /* remove signaling task */
156/*------------------------------------------------------------------*/
157/* Signaling service primitives */
158/*------------------------------------------------------------------*/
159#define CALL_REQ 1 /* call request */
160#define CALL_CON 1 /* call confirmation */
161#define CALL_IND 2 /* incoming call connected */
162#define LISTEN_REQ 2 /* listen request */
163#define HANGUP 3 /* hangup request/indication */
164#define SUSPEND 4 /* call suspend request/confirm */
165#define RESUME 5 /* call resume request/confirm */
166#define SUSPEND_REJ 6 /* suspend rejected indication */
167#define USER_DATA 8 /* user data for user to user signaling */
168#define CONGESTION 9 /* network congestion indication */
169#define INDICATE_REQ 10 /* request to indicate an incoming call */
170#define INDICATE_IND 10 /* indicates that there is an incoming call */
171#define CALL_RES 11 /* accept an incoming call */
172#define CALL_ALERT 12 /* send ALERT for incoming call */
173#define INFO_REQ 13 /* INFO request */
174#define INFO_IND 13 /* INFO indication */
175#define REJECT 14 /* reject an incoming call */
176#define RESOURCES 15 /* reserve B-Channel hardware resources */
177#define HW_CTRL 16 /* B-Channel hardware IOCTL req/ind */
178#define TEL_CTRL 16 /* Telephone control request/indication */
179#define STATUS_REQ 17 /* Request D-State (returned in INFO_IND) */
180#define FAC_REG_REQ 18 /* 1TR6 connection independent fac reg */
181#define FAC_REG_ACK 19 /* 1TR6 fac registration acknowledge */
182#define FAC_REG_REJ 20 /* 1TR6 fac registration reject */
183#define CALL_COMPLETE 21/* send a CALL_PROC for incoming call */
184#define SW_CTRL 22 /* extended software features */
185#define REGISTER_REQ 23 /* Q.931 connection independent reg req */
186#define REGISTER_IND 24 /* Q.931 connection independent reg ind */
187#define FACILITY_REQ 25 /* Q.931 connection independent fac req */
188#define FACILITY_IND 26 /* Q.931 connection independent fac ind */
189#define NCR_INFO_REQ 27 /* INFO_REQ with NULL CR */
190#define GCR_MIM_REQ 28 /* MANAGEMENT_INFO_REQ with global CR */
191#define SIG_CTRL 29 /* Control for Signalling Hardware */
192#define DSP_CTRL 30 /* Control for DSPs */
193#define LAW_REQ 31 /* Law config request for (returns info_i) */
194#define SPID_CTRL 32 /* Request/indication SPID related */
195#define NCR_FACILITY 33 /* Request/indication with NULL/DUMMY CR */
196#define CALL_HOLD 34 /* Request/indication to hold a CALL */
197#define CALL_RETRIEVE 35 /* Request/indication to retrieve a CALL */
198#define CALL_HOLD_ACK 36 /* OK of hold a CALL */
199#define CALL_RETRIEVE_ACK 37 /* OK of retrieve a CALL */
200#define CALL_HOLD_REJ 38 /* Reject of hold a CALL */
201#define CALL_RETRIEVE_REJ 39 /* Reject of retrieve a call */
202#define GCR_RESTART 40 /* Send/Receive Restart message */
203#define S_SERVICE 41 /* Send/Receive Supplementary Service */
204#define S_SERVICE_REJ 42 /* Reject Supplementary Service indication */
205#define S_SUPPORTED 43 /* Req/Ind to get Supported Services */
206#define STATUS_ENQ 44 /* Req to send the D-ch request if !state0 */
207#define CALL_GUARD 45 /* Req/Ind to use the FLAGS_CALL_OUTCHECK */
208#define CALL_GUARD_HP 46 /* Call Guard function to reject a call */
209#define CALL_GUARD_IF 47 /* Call Guard function, inform the appl */
210#define SSEXT_REQ 48 /* Supplem.Serv./QSIG specific request */
211#define SSEXT_IND 49 /* Supplem.Serv./QSIG specific indication */
212/* reserved commands for the US protocols */
213#define INT_3PTY_NIND 50 /* US specific indication */
214#define INT_CF_NIND 51 /* US specific indication */
215#define INT_3PTY_DROP 52 /* US specific indication */
216#define INT_MOVE_CONF 53 /* US specific indication */
217#define INT_MOVE_RC 54 /* US specific indication */
218#define INT_MOVE_FLIPPED_CONF 55 /* US specific indication */
219#define INT_X5NI_OK 56 /* internal transfer OK indication */
220#define INT_XDMS_START 57 /* internal transfer OK indication */
221#define INT_XDMS_STOP 58 /* internal transfer finish indication */
222#define INT_XDMS_STOP2 59 /* internal transfer send FA */
223#define INT_CUSTCONF_REJ 60 /* internal conference reject */
224#define INT_CUSTXFER 61 /* internal transfer request */
225#define INT_CUSTX_NIND 62 /* internal transfer ack */
226#define INT_CUSTXREJ_NIND 63 /* internal transfer rej */
227#define INT_X5NI_CF_XFER 64 /* internal transfer OK indication */
228#define VSWITCH_REQ 65 /* communication between protocol and */
229#define VSWITCH_IND 66 /* capifunctions for D-CH-switching */
230#define MWI_POLL 67 /* Message Waiting Status Request fkt */
231#define CALL_PEND_NOTIFY 68 /* notify capi to set new listen */
232#define DO_NOTHING 69 /* dont do somethin if you get this */
233#define INT_CT_REJ 70 /* ECT rejected internal command */
234#define CALL_HOLD_COMPLETE 71 /* In NT Mode indicate hold complete */
235#define CALL_RETRIEVE_COMPLETE 72 /* In NT Mode indicate retrieve complete */
236/*------------------------------------------------------------------*/
237/* management service primitives */
238/*------------------------------------------------------------------*/
239#define MAN_READ 2
240#define MAN_WRITE 3
241#define MAN_EXECUTE 4
242#define MAN_EVENT_ON 5
243#define MAN_EVENT_OFF 6
244#define MAN_LOCK 7
245#define MAN_UNLOCK 8
246#define MAN_INFO_IND 2
247#define MAN_EVENT_IND 3
248#define MAN_TRACE_IND 4
249#define MAN_COMBI_IND 9
250#define MAN_ESC 0x80
251/*------------------------------------------------------------------*/
252/* return code coding */
253/*------------------------------------------------------------------*/
254#define UNKNOWN_COMMAND 0x01 /* unknown command */
255#define WRONG_COMMAND 0x02 /* wrong command */
256#define WRONG_ID 0x03 /* unknown task/entity id */
257#define WRONG_CH 0x04 /* wrong task/entity id */
258#define UNKNOWN_IE 0x05 /* unknown information el. */
259#define WRONG_IE 0x06 /* wrong information el. */
260#define OUT_OF_RESOURCES 0x07 /* ISDN-S card out of res. */
261#define ISDN_GUARD_REJ 0x09 /* ISDN-Guard SuppServ rej */
262#define N_FLOW_CONTROL 0x10 /* Flow-Control, retry */
263#define ASSIGN_RC 0xe0 /* ASSIGN acknowledgement */
264#define ASSIGN_OK 0xef /* ASSIGN OK */
265#define OK_FC 0xfc /* Flow-Control RC */
266#define READY_INT 0xfd /* Ready interrupt */
267#define TIMER_INT 0xfe /* timer interrupt */
268#define OK 0xff /* command accepted */
269/*------------------------------------------------------------------*/
270/* information elements */
271/*------------------------------------------------------------------*/
272#define SHIFT 0x90 /* codeset shift */
273#define MORE 0xa0 /* more data */
274#define SDNCMPL 0xa1 /* sending complete */
275#define CL 0xb0 /* congestion level */
276 /* codeset 0 */
277#define SMSG 0x00 /* segmented message */
278#define BC 0x04 /* Bearer Capability */
279#define CAU 0x08 /* cause */
280#define CAD 0x0c /* Connected address */
281#define CAI 0x10 /* call identity */
282#define CHI 0x18 /* channel identification */
283#define LLI 0x19 /* logical link id */
284#define CHA 0x1a /* charge advice */
285#define FTY 0x1c /* Facility */
286#define DT 0x29 /* ETSI date/time */
287#define KEY 0x2c /* keypad information element */
288#define UID 0x2d /* User id information element */
289#define DSP 0x28 /* display */
290#define SIG 0x34 /* signalling hardware control */
291#define OAD 0x6c /* origination address */
292#define OSA 0x6d /* origination sub-address */
293#define CPN 0x70 /* called party number */
294#define DSA 0x71 /* destination sub-address */
295#define RDX 0x73 /* redirecting number extended */
296#define RDN 0x74 /* redirecting number */
297#define RIN 0x76 /* redirection number */
298#define IUP 0x76 /* VN6 rerouter->PCS (codeset 6) */
299#define IPU 0x77 /* VN6 PCS->rerouter (codeset 6) */
300#define RI 0x79 /* restart indicator */
301#define MIE 0x7a /* management info element */
302#define LLC 0x7c /* low layer compatibility */
303#define HLC 0x7d /* high layer compatibility */
304#define UUI 0x7e /* user user information */
305#define ESC 0x7f /* escape extension */
306#define DLC 0x20 /* data link layer configuration */
307#define NLC 0x21 /* network layer configuration */
308#define REDIRECT_IE 0x22 /* redirection request/indication data */
309#define REDIRECT_NET_IE 0x23 /* redirection network override data */
310 /* codeset 6 */
311#define SIN 0x01 /* service indicator */
312#define CIF 0x02 /* charging information */
313#define DATE 0x03 /* date */
314#define CPS 0x07 /* called party status */
315/*------------------------------------------------------------------*/
316/* ESC information elements */
317/*------------------------------------------------------------------*/
318#define MSGTYPEIE 0x7a /* Messagetype info element */
319#define CRIE 0x7b /* INFO info element */
320#define CODESET6IE 0xec /* Tunnel for Codeset 6 IEs */
321#define VSWITCHIE 0xed /* VSwitch info element */
322#define SSEXTIE 0xee /* Supplem. Service info element */
323#define PROFILEIE 0xef /* Profile info element */
324/*------------------------------------------------------------------*/
325/* TEL_CTRL contents */
326/*------------------------------------------------------------------*/
327#define RING_ON 0x01
328#define RING_OFF 0x02
329#define HANDS_FREE_ON 0x03
330#define HANDS_FREE_OFF 0x04
331#define ON_HOOK 0x80
332#define OFF_HOOK 0x90
333/* operation values used by ETSI supplementary services */
334#define THREE_PTY_BEGIN 0x04
335#define THREE_PTY_END 0x05
336#define ECT_EXECUTE 0x06
337#define ACTIVATION_DIVERSION 0x07
338#define DEACTIVATION_DIVERSION 0x08
339#define CALL_DEFLECTION 0x0D
340#define INTERROGATION_DIVERSION 0x0B
341#define INTERROGATION_SERV_USR_NR 0x11
342#define ACTIVATION_MWI 0x20
343#define DEACTIVATION_MWI 0x21
344#define MWI_INDICATION 0x22
345#define MWI_RESPONSE 0x23
346#define CONF_BEGIN 0x28
347#define CONF_ADD 0x29
348#define CONF_SPLIT 0x2a
349#define CONF_DROP 0x2b
350#define CONF_ISOLATE 0x2c
351#define CONF_REATTACH 0x2d
352#define CONF_PARTYDISC 0x2e
353#define CCBS_INFO_RETAIN 0x2f
354#define CCBS_ERASECALLLINKAGEID 0x30
355#define CCBS_STOP_ALERTING 0x31
356#define CCBS_REQUEST 0x32
357#define CCBS_DEACTIVATE 0x33
358#define CCBS_INTERROGATE 0x34
359#define CCBS_STATUS 0x35
360#define CCBS_ERASE 0x36
361#define CCBS_B_FREE 0x37
362#define CCNR_INFO_RETAIN 0x38
363#define CCBS_REMOTE_USER_FREE 0x39
364#define CCNR_REQUEST 0x3a
365#define CCNR_INTERROGATE 0x3b
366#define GET_SUPPORTED_SERVICES 0xff
367#define DIVERSION_PROCEDURE_CFU 0x70
368#define DIVERSION_PROCEDURE_CFB 0x71
369#define DIVERSION_PROCEDURE_CFNR 0x72
370#define DIVERSION_DEACTIVATION_CFU 0x80
371#define DIVERSION_DEACTIVATION_CFB 0x81
372#define DIVERSION_DEACTIVATION_CFNR 0x82
373#define DIVERSION_INTERROGATE_NUM 0x11
374#define DIVERSION_INTERROGATE_CFU 0x60
375#define DIVERSION_INTERROGATE_CFB 0x61
376#define DIVERSION_INTERROGATE_CFNR 0x62
377/* Service Masks */
378#define SMASK_HOLD_RETRIEVE 0x00000001
379#define SMASK_TERMINAL_PORTABILITY 0x00000002
380#define SMASK_ECT 0x00000004
381#define SMASK_3PTY 0x00000008
382#define SMASK_CALL_FORWARDING 0x00000010
383#define SMASK_CALL_DEFLECTION 0x00000020
384#define SMASK_MCID 0x00000040
385#define SMASK_CCBS 0x00000080
386#define SMASK_MWI 0x00000100
387#define SMASK_CCNR 0x00000200
388#define SMASK_CONF 0x00000400
389/* ----------------------------------------------
390 Types of transfers used to transfer the
391 information in the 'struct RC->Reserved2[8]'
392 The information is transferred as 2 dwords
393 (2 4Byte unsigned values)
394 First of them is the transfer type.
395 2^32-1 possible messages are possible in this way.
396 The context of the second one had no meaning
397 ---------------------------------------------- */
398#define DIVA_RC_TYPE_NONE 0x00000000
399#define DIVA_RC_TYPE_REMOVE_COMPLETE 0x00000008
400#define DIVA_RC_TYPE_STREAM_PTR 0x00000009
401#define DIVA_RC_TYPE_CMA_PTR 0x0000000a
402#define DIVA_RC_TYPE_OK_FC 0x0000000b
403#define DIVA_RC_TYPE_RX_DMA 0x0000000c
404/* ------------------------------------------------------
405 IO Control codes for IN BAND SIGNALING
406 ------------------------------------------------------ */
407#define CTRL_L1_SET_SIG_ID 5
408#define CTRL_L1_SET_DAD 6
409#define CTRL_L1_RESOURCES 7
410/* ------------------------------------------------------ */
411/* ------------------------------------------------------
412 Layer 2 types
413 ------------------------------------------------------ */
414#define X75T 1 /* x.75 for ttx */
415#define TRF 2 /* transparent with hdlc framing */
416#define TRF_IN 3 /* transparent with hdlc fr. inc. */
417#define SDLC 4 /* sdlc, sna layer-2 */
418#define X75 5 /* x.75 for btx */
419#define LAPD 6 /* lapd (Q.921) */
420#define X25_L2 7 /* x.25 layer-2 */
421#define V120_L2 8 /* V.120 layer-2 protocol */
422#define V42_IN 9 /* V.42 layer-2 protocol, incomming */
423#define V42 10 /* V.42 layer-2 protocol */
424#define MDM_ATP 11 /* AT Parser built in the L2 */
425#define X75_V42BIS 12 /* x.75 with V.42bis */
426#define RTPL2_IN 13 /* RTP layer-2 protocol, incomming */
427#define RTPL2 14 /* RTP layer-2 protocol */
428#define V120_V42BIS 15 /* V.120 asynchronous mode supporting V.42bis compression */
429#define LISTENER 27 /* Layer 2 to listen line */
430#define MTP2 28 /* MTP2 Layer 2 */
431#define PIAFS_CRC 29 /* PIAFS Layer 2 with CRC calculation at L2 */
432/* ------------------------------------------------------
433 PIAFS DLC DEFINITIONS
434 ------------------------------------------------------ */
435#define PIAFS_64K 0x01
436#define PIAFS_VARIABLE_SPEED 0x02
437#define PIAFS_CHINESE_SPEED 0x04
438#define PIAFS_UDATA_ABILITY_ID 0x80
439#define PIAFS_UDATA_ABILITY_DCDON 0x01
440#define PIAFS_UDATA_ABILITY_DDI 0x80
441/*
442DLC of PIAFS :
443Byte | 8 7 6 5 4 3 2 1
444-----+--------------------------------------------------------
445 0 | 0 0 1 0 0 0 0 0 Data Link Configuration
446 1 | X X X X X X X X Length of IE (at least 15 Bytes)
447 2 | 0 0 0 0 0 0 0 0 max. information field, LOW byte (not used, fix 73 Bytes)
448 3 | 0 0 0 0 0 0 0 0 max. information field, HIGH byte (not used, fix 73 Bytes)
449 4 | 0 0 0 0 0 0 0 0 address A (not used)
450 5 | 0 0 0 0 0 0 0 0 address B (not used)
451 6 | 0 0 0 0 0 0 0 0 Mode (not used, fix 128)
452 7 | 0 0 0 0 0 0 0 0 Window Size (not used, fix 127)
453 8 | X X X X X X X X XID Length, Low Byte (at least 7 Bytes)
454 9 | X X X X X X X X XID Length, High Byte
455 10 | 0 0 0 0 0 C V S PIAFS Protocol Speed configuration -> Note(1)
456 | S = 0 -> Protocol Speed is 32K
457 | S = 1 -> Protocol Speed is 64K
458 | V = 0 -> Protocol Speed is fixed
459 | V = 1 -> Protocol Speed is variable
460 | C = 0 -> speed setting according to standard
461 | C = 1 -> speed setting for chinese implementation
462 11 | 0 0 0 0 0 0 R T P0 - V42bis Compression enable/disable, Low Byte
463 | T = 0 -> Transmit Direction enable
464 | T = 1 -> Transmit Direction disable
465 | R = 0 -> Receive Direction enable
466 | R = 1 -> Receive Direction disable
467 13 | 0 0 0 0 0 0 0 0 P0 - V42bis Compression enable/disable, High Byte
468 14 | X X X X X X X X P1 - V42bis Dictionary Size, Low Byte
469 15 | X X X X X X X X P1 - V42bis Dictionary Size, High Byte
470 16 | X X X X X X X X P2 - V42bis String Length, Low Byte
471 17 | X X X X X X X X P2 - V42bis String Length, High Byte
472 18 | X X X X X X X X PIAFS extension length
473 19 | 1 0 0 0 0 0 0 0 PIAFS extension Id (0x80) - UDATA abilities
474 20 | U 0 0 0 0 0 0 D UDATA abilities -> Note (2)
475 | up to now the following Bits are defined:
476 | D - signal DCD ON
477 | U - use extensive UDATA control communication
478 | for DDI test application
479+ Note (1): ----------+------+-----------------------------------------+
480| PIAFS Protocol | Bit | |
481| Speed configuration | S | Bit 1 - Protocol Speed |
482| | | 0 - 32K |
483| | | 1 - 64K (default) |
484| | V | Bit 2 - Variable Protocol Speed |
485| | | 0 - Speed is fix |
486| | | 1 - Speed is variable (default) |
487| | | OVERWRITES 32k Bit 1 |
488| | C | Bit 3 0 - Speed Settings according to |
489| | | PIAFS specification |
490| | | 1 - Speed setting for chinese |
491| | | PIAFS implementation |
492| | | Explanation for chinese speed settings: |
493| | | if Bit 3 is set the following |
494| | | rules apply: |
495| | | Bit1=0 Bit2=0: 32k fix |
496| | | Bit1=1 Bit2=0: 64k fix |
497| | | Bit1=0 Bit2=1: PIAFS is trying |
498| | | to negotiate 32k is that is |
499| | | not possible it tries to |
500| | | negotiate 64k |
501| | | Bit1=1 Bit2=1: PIAFS is trying |
502| | | to negotiate 64k is that is |
503| | | not possible it tries to |
504| | | negotiate 32k |
505+ Note (2): ----------+------+-----------------------------------------+
506| PIAFS | Bit | this byte defines the usage of UDATA |
507| Implementation | | control communication |
508| UDATA usage | D | Bit 1 - DCD-ON signalling |
509| | | 0 - no DCD-ON is signalled |
510| | | (default) |
511| | | 1 - DCD-ON will be signalled |
512| | U | Bit 8 - DDI test application UDATA |
513| | | control communication |
514| | | 0 - no UDATA control |
515| | | communication (default) |
516| | | sets as well the DCD-ON |
517| | | signalling |
518| | | 1 - UDATA control communication |
519| | | ATTENTION: Do not use these |
520| | | setting if you |
521| | | are not really |
522| | | that you need it |
523| | | and you know |
524| | | exactly what you |
525| | | are doing. |
526| | | You can easily |
527| | | disable any |
528| | | data transfer. |
529+---------------------+------+-----------------------------------------+
530*/
531/* ------------------------------------------------------
532 LISTENER DLC DEFINITIONS
533 ------------------------------------------------------ */
534#define LISTENER_FEATURE_MASK_CUMMULATIVE 0x0001
535/* ------------------------------------------------------
536 LISTENER META-FRAME CODE/PRIMITIVE DEFINITIONS
537 ------------------------------------------------------ */
538#define META_CODE_LL_UDATA_RX 0x01
539#define META_CODE_LL_UDATA_TX 0x02
540#define META_CODE_LL_DATA_RX 0x03
541#define META_CODE_LL_DATA_TX 0x04
542#define META_CODE_LL_MDATA_RX 0x05
543#define META_CODE_LL_MDATA_TX 0x06
544#define META_CODE_EMPTY 0x10
545#define META_CODE_LOST_FRAMES 0x11
546#define META_FLAG_TRUNCATED 0x0001
547/*------------------------------------------------------------------*/
548/* CAPI-like profile to indicate features on LAW_REQ */
549/*------------------------------------------------------------------*/
550#define GL_INTERNAL_CONTROLLER_SUPPORTED 0x00000001L
551#define GL_EXTERNAL_EQUIPMENT_SUPPORTED 0x00000002L
552#define GL_HANDSET_SUPPORTED 0x00000004L
553#define GL_DTMF_SUPPORTED 0x00000008L
554#define GL_SUPPLEMENTARY_SERVICES_SUPPORTED 0x00000010L
555#define GL_CHANNEL_ALLOCATION_SUPPORTED 0x00000020L
556#define GL_BCHANNEL_OPERATION_SUPPORTED 0x00000040L
557#define GL_LINE_INTERCONNECT_SUPPORTED 0x00000080L
558#define B1_HDLC_SUPPORTED 0x00000001L
559#define B1_TRANSPARENT_SUPPORTED 0x00000002L
560#define B1_V110_ASYNC_SUPPORTED 0x00000004L
561#define B1_V110_SYNC_SUPPORTED 0x00000008L
562#define B1_T30_SUPPORTED 0x00000010L
563#define B1_HDLC_INVERTED_SUPPORTED 0x00000020L
564#define B1_TRANSPARENT_R_SUPPORTED 0x00000040L
565#define B1_MODEM_ALL_NEGOTIATE_SUPPORTED 0x00000080L
566#define B1_MODEM_ASYNC_SUPPORTED 0x00000100L
567#define B1_MODEM_SYNC_HDLC_SUPPORTED 0x00000200L
568#define B2_X75_SUPPORTED 0x00000001L
569#define B2_TRANSPARENT_SUPPORTED 0x00000002L
570#define B2_SDLC_SUPPORTED 0x00000004L
571#define B2_LAPD_SUPPORTED 0x00000008L
572#define B2_T30_SUPPORTED 0x00000010L
573#define B2_PPP_SUPPORTED 0x00000020L
574#define B2_TRANSPARENT_NO_CRC_SUPPORTED 0x00000040L
575#define B2_MODEM_EC_COMPRESSION_SUPPORTED 0x00000080L
576#define B2_X75_V42BIS_SUPPORTED 0x00000100L
577#define B2_V120_ASYNC_SUPPORTED 0x00000200L
578#define B2_V120_ASYNC_V42BIS_SUPPORTED 0x00000400L
579#define B2_V120_BIT_TRANSPARENT_SUPPORTED 0x00000800L
580#define B2_LAPD_FREE_SAPI_SEL_SUPPORTED 0x00001000L
581#define B3_TRANSPARENT_SUPPORTED 0x00000001L
582#define B3_T90NL_SUPPORTED 0x00000002L
583#define B3_ISO8208_SUPPORTED 0x00000004L
584#define B3_X25_DCE_SUPPORTED 0x00000008L
585#define B3_T30_SUPPORTED 0x00000010L
586#define B3_T30_WITH_EXTENSIONS_SUPPORTED 0x00000020L
587#define B3_RESERVED_SUPPORTED 0x00000040L
588#define B3_MODEM_SUPPORTED 0x00000080L
589#define MANUFACTURER_FEATURE_SLAVE_CODEC 0x00000001L
590#define MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS 0x00000002L
591#define MANUFACTURER_FEATURE_HARDDTMF 0x00000004L
592#define MANUFACTURER_FEATURE_SOFTDTMF_SEND 0x00000008L
593#define MANUFACTURER_FEATURE_DTMF_PARAMETERS 0x00000010L
594#define MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE 0x00000020L
595#define MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD 0x00000040L
596#define MANUFACTURER_FEATURE_V18 0x00000080L
597#define MANUFACTURER_FEATURE_MIXER_CH_CH 0x00000100L
598#define MANUFACTURER_FEATURE_MIXER_CH_PC 0x00000200L
599#define MANUFACTURER_FEATURE_MIXER_PC_CH 0x00000400L
600#define MANUFACTURER_FEATURE_MIXER_PC_PC 0x00000800L
601#define MANUFACTURER_FEATURE_ECHO_CANCELLER 0x00001000L
602#define MANUFACTURER_FEATURE_RTP 0x00002000L
603#define MANUFACTURER_FEATURE_T38 0x00004000L
604#define MANUFACTURER_FEATURE_TRANSP_DELIVERY_CONF 0x00008000L
605#define MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL 0x00010000L
606#define MANUFACTURER_FEATURE_OOB_CHANNEL 0x00020000L
607#define MANUFACTURER_FEATURE_IN_BAND_CHANNEL 0x00040000L
608#define MANUFACTURER_FEATURE_IN_BAND_FEATURE 0x00080000L
609#define MANUFACTURER_FEATURE_PIAFS 0x00100000L
610#define MANUFACTURER_FEATURE_DTMF_TONE 0x00200000L
611#define MANUFACTURER_FEATURE_FAX_PAPER_FORMATS 0x00400000L
612#define MANUFACTURER_FEATURE_OK_FC_LABEL 0x00800000L
613#define MANUFACTURER_FEATURE_VOWN 0x01000000L
614#define MANUFACTURER_FEATURE_XCONNECT 0x02000000L
615#define MANUFACTURER_FEATURE_DMACONNECT 0x04000000L
616#define MANUFACTURER_FEATURE_AUDIO_TAP 0x08000000L
617#define MANUFACTURER_FEATURE_FAX_NONSTANDARD 0x10000000L
618#define MANUFACTURER_FEATURE_SS7 0x20000000L
619#define MANUFACTURER_FEATURE_MADAPTER 0x40000000L
620#define MANUFACTURER_FEATURE_MEASURE 0x80000000L
621#define MANUFACTURER_FEATURE2_LISTENING 0x00000001L
622#define MANUFACTURER_FEATURE2_SS_DIFFCONTPOSSIBLE 0x00000002L
623#define MANUFACTURER_FEATURE2_GENERIC_TONE 0x00000004L
624#define MANUFACTURER_FEATURE2_COLOR_FAX 0x00000008L
625#define MANUFACTURER_FEATURE2_SS_ECT_DIFFCONTPOSSIBLE 0x00000010L
626#define RTP_PRIM_PAYLOAD_PCMU_8000 0
627#define RTP_PRIM_PAYLOAD_1016_8000 1
628#define RTP_PRIM_PAYLOAD_G726_32_8000 2
629#define RTP_PRIM_PAYLOAD_GSM_8000 3
630#define RTP_PRIM_PAYLOAD_G723_8000 4
631#define RTP_PRIM_PAYLOAD_DVI4_8000 5
632#define RTP_PRIM_PAYLOAD_DVI4_16000 6
633#define RTP_PRIM_PAYLOAD_LPC_8000 7
634#define RTP_PRIM_PAYLOAD_PCMA_8000 8
635#define RTP_PRIM_PAYLOAD_G722_16000 9
636#define RTP_PRIM_PAYLOAD_QCELP_8000 12
637#define RTP_PRIM_PAYLOAD_G728_8000 14
638#define RTP_PRIM_PAYLOAD_G729_8000 18
639#define RTP_PRIM_PAYLOAD_GSM_HR_8000 30
640#define RTP_PRIM_PAYLOAD_GSM_EFR_8000 31
641#define RTP_ADD_PAYLOAD_BASE 32
642#define RTP_ADD_PAYLOAD_RED 32
643#define RTP_ADD_PAYLOAD_CN_8000 33
644#define RTP_ADD_PAYLOAD_DTMF 34
645#define RTP_PRIM_PAYLOAD_PCMU_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_PCMU_8000)
646#define RTP_PRIM_PAYLOAD_1016_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_1016_8000)
647#define RTP_PRIM_PAYLOAD_G726_32_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_G726_32_8000)
648#define RTP_PRIM_PAYLOAD_GSM_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_GSM_8000)
649#define RTP_PRIM_PAYLOAD_G723_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_G723_8000)
650#define RTP_PRIM_PAYLOAD_DVI4_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_DVI4_8000)
651#define RTP_PRIM_PAYLOAD_DVI4_16000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_DVI4_16000)
652#define RTP_PRIM_PAYLOAD_LPC_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_LPC_8000)
653#define RTP_PRIM_PAYLOAD_PCMA_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_PCMA_8000)
654#define RTP_PRIM_PAYLOAD_G722_16000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_G722_16000)
655#define RTP_PRIM_PAYLOAD_QCELP_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_QCELP_8000)
656#define RTP_PRIM_PAYLOAD_G728_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_G728_8000)
657#define RTP_PRIM_PAYLOAD_G729_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_G729_8000)
658#define RTP_PRIM_PAYLOAD_GSM_HR_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_GSM_HR_8000)
659#define RTP_PRIM_PAYLOAD_GSM_EFR_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_GSM_EFR_8000)
660#define RTP_ADD_PAYLOAD_RED_SUPPORTED (1L << (RTP_ADD_PAYLOAD_RED - RTP_ADD_PAYLOAD_BASE))
661#define RTP_ADD_PAYLOAD_CN_8000_SUPPORTED (1L << (RTP_ADD_PAYLOAD_CN_8000 - RTP_ADD_PAYLOAD_BASE))
662#define RTP_ADD_PAYLOAD_DTMF_SUPPORTED (1L << (RTP_ADD_PAYLOAD_DTMF - RTP_ADD_PAYLOAD_BASE))
663/* virtual switching definitions */
664#define VSJOIN 1
665#define VSTRANSPORT 2
666#define VSGETPARAMS 3
667#define VSCAD 1
668#define VSRXCPNAME 2
669#define VSCALLSTAT 3
670#define VSINVOKEID 4
671#define VSCLMRKS 5
672#define VSTBCTIDENT 6
673#define VSETSILINKID 7
674#define VSSAMECONTROLLER 8
675/* Errorcodes for VSETSILINKID begin */
676#define VSETSILINKIDRRWC 1
677#define VSETSILINKIDREJECT 2
678#define VSETSILINKIDTIMEOUT 3
679#define VSETSILINKIDFAILCOUNT 4
680#define VSETSILINKIDERROR 5
681/* Errorcodes for VSETSILINKID end */
682/* -----------------------------------------------------------**
683** The PROTOCOL_FEATURE_STRING in feature.h (included **
684** in prstart.sx and astart.sx) defines capabilities and **
685** features of the actual protocol code. It's used as a bit **
686** mask. **
687** The following Bits are defined: **
688** -----------------------------------------------------------*/
689#define PROTCAP_TELINDUS 0x0001 /* Telindus Variant of protocol code */
690#define PROTCAP_MAN_IF 0x0002 /* Management interface implemented */
691#define PROTCAP_V_42 0x0004 /* V42 implemented */
692#define PROTCAP_V90D 0x0008 /* V.90D (implies up to 384k DSP code) */
693#define PROTCAP_EXTD_FAX 0x0010 /* Extended FAX (ECM, 2D, T6, Polling) */
694#define PROTCAP_EXTD_RXFC 0x0020 /* RxFC (Extd Flow Control), OOB Chnl */
695#define PROTCAP_VOIP 0x0040 /* VoIP (implies up to 512k DSP code) */
696#define PROTCAP_CMA_ALLPR 0x0080 /* CMA support for all NL primitives */
697#define PROTCAP_FREE8 0x0100 /* not used */
698#define PROTCAP_FREE9 0x0200 /* not used */
699#define PROTCAP_FREE10 0x0400 /* not used */
700#define PROTCAP_FREE11 0x0800 /* not used */
701#define PROTCAP_FREE12 0x1000 /* not used */
702#define PROTCAP_FREE13 0x2000 /* not used */
703#define PROTCAP_FREE14 0x4000 /* not used */
704#define PROTCAP_EXTENSION 0x8000 /* used for future extentions */
705/* -----------------------------------------------------------* */
706/* Onhook data transmission ETS30065901 */
707/* Message Type */
708/*#define RESERVED4 0x4*/
709#define CALL_SETUP 0x80
710#define MESSAGE_WAITING_INDICATOR 0x82
711/*#define RESERVED84 0x84*/
712/*#define RESERVED85 0x85*/
713#define ADVICE_OF_CHARGE 0x86
714/*1111 0001
715to
7161111 1111
717F1H - Reserved for network operator use
718to
719FFH*/
720/* Parameter Types */
721#define DATE_AND_TIME 1
722#define CLI_PARAMETER_TYPE 2
723#define CALLED_DIRECTORY_NUMBER_PARAMETER_TYPE 3
724#define REASON_FOR_ABSENCE_OF_CLI_PARAMETER_TYPE 4
725#define NAME_PARAMETER_TYPE 7
726#define REASON_FOR_ABSENCE_OF_CALLING_PARTY_NAME_PARAMETER_TYPE 8
727#define VISUAL_INDICATOR_PARAMETER_TYPE 0xb
728#define COMPLEMENTARY_CLI_PARAMETER_TYPE 0x10
729#define CALL_TYPE_PARAMETER_TYPE 0x11
730#define FIRST_CALLED_LINE_DIRECTORY_NUMBER_PARAMETER_TYPE 0x12
731#define NETWORK_MESSAGE_SYSTEM_STATUS_PARAMETER_TYPE 0x13
732#define FORWARDED_CALL_TYPE_PARAMETER_TYPE 0x15
733#define TYPE_OF_CALLING_USER_PARAMETER_TYPE 0x16
734#define REDIRECTING_NUMBER_PARAMETER_TYPE 0x1a
735#define EXTENSION_FOR_NETWORK_OPERATOR_USE_PARAMETER_TYPE 0xe0
736/* -----------------------------------------------------------* */
737#else
738#endif /* PC_H_INCLUDED } */
diff --git a/drivers/isdn/hardware/eicon/pc_init.h b/drivers/isdn/hardware/eicon/pc_init.h
new file mode 100644
index 000000000000..a616fc9d32e9
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/pc_init.h
@@ -0,0 +1,267 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef PC_INIT_H_
27#define PC_INIT_H_
28/*------------------------------------------------------------------*/
29/*
30 Initialisation parameters for the card
31 0x0008 <byte> TEI
32 0x0009 <byte> NT2 flag
33 0x000a <byte> Default DID length
34 0x000b <byte> Disable watchdog flag
35 0x000c <byte> Permanent connection flag
36 0x000d <byte> Bit 3-8: L1 Hunt Group/Tristate
37 0x000d <byte> Bit 1: QSig small CR length if set to 1
38 0x000d <byte> Bit 2: QSig small CHI length if set to 1
39 0x000e <byte> Bit 1-3: Stable L2, 0=OnDemand,1=NoDisc,2=permanent
40 0x000e <byte> Bit 4: NT mode
41 0x000e <byte> Bit 5: QSig Channel ID format
42 0x000e <byte> Bit 6: QSig Call Forwarding Allowed Flag
43 0x000e <byte> Bit 7: Disable AutoSPID Flag
44 0x000f <byte> No order check flag
45 0x0010 <byte> Force companding type:0=default,1=a-law,2=u-law
46 0x0012 <byte> Low channel flag
47 0x0013 <byte> Protocol version
48 0x0014 <byte> CRC4 option:0=default,1=double_frm,2=multi_frm,3=auto
49 0x0015 <byte> Bit 0: NoHscx30, Bit 1: Loopback flag, Bit 2: ForceHscx30
50 0x0016 <byte> DSP info
51 0x0017-0x0019 Serial number
52 0x001a <byte> Card type
53 0x0020 <string> OAD 0
54 0x0040 <string> OSA 0
55 0x0060 <string> SPID 0 (if not T.1)
56 0x0060 <struct> if T.1: Robbed Bit Configuration
57 0x0060 length (8)
58 0x0061 RBS Answer Delay
59 0x0062 RBS Config Bit 3, 4:
60 0 0 -> Wink Start
61 1 0 -> Loop Start
62 0 1 -> Ground Start
63 1 1 -> reserved
64 Bit 5, 6:
65 0 0 -> Pulse Dial -> Rotary
66 1 0 -> DTMF
67 0 1 -> MF
68 1 1 -> reserved
69 0x0063 RBS RX Digit Timeout
70 0x0064 RBS Bearer Capability
71 0x0065-0x0069 RBS Debug Mask
72 0x0080 <string> OAD 1
73 0x00a0 <string> OSA 1
74 0x00c0 <string> SPID 1
75 0x00e0 <w-element list> Additional configuration
76*/
77#define PCINIT_END_OF_LIST 0x00
78#define PCINIT_MODEM_GUARD_TONE 0x01
79#define PCINIT_MODEM_MIN_SPEED 0x02
80#define PCINIT_MODEM_MAX_SPEED 0x03
81#define PCINIT_MODEM_PROTOCOL_OPTIONS 0x04
82#define PCINIT_FAX_OPTIONS 0x05
83#define PCINIT_FAX_MAX_SPEED 0x06
84#define PCINIT_MODEM_OPTIONS 0x07
85#define PCINIT_MODEM_NEGOTIATION_MODE 0x08
86#define PCINIT_MODEM_MODULATIONS_MASK 0x09
87#define PCINIT_MODEM_TRANSMIT_LEVEL 0x0a
88#define PCINIT_FAX_DISABLED_RESOLUTIONS 0x0b
89#define PCINIT_FAX_MAX_RECORDING_WIDTH 0x0c
90#define PCINIT_FAX_MAX_RECORDING_LENGTH 0x0d
91#define PCINIT_FAX_MIN_SCANLINE_TIME 0x0e
92#define PCINIT_US_EKTS_CACH_HANDLES 0x0f
93#define PCINIT_US_EKTS_BEGIN_CONF 0x10
94#define PCINIT_US_EKTS_DROP_CONF 0x11
95#define PCINIT_US_EKTS_CALL_TRANSFER 0x12
96#define PCINIT_RINGERTONE_OPTION 0x13
97#define PCINIT_CARD_ADDRESS 0x14
98#define PCINIT_FPGA_FEATURES 0x15
99#define PCINIT_US_EKTS_MWI 0x16
100#define PCINIT_MODEM_SPEAKER_CONTROL 0x17
101#define PCINIT_MODEM_SPEAKER_VOLUME 0x18
102#define PCINIT_MODEM_CARRIER_WAIT_TIME 0x19
103#define PCINIT_MODEM_CARRIER_LOSS_TIME 0x1a
104#define PCINIT_UNCHAN_B_MASK 0x1b
105#define PCINIT_PART68_LIMITER 0x1c
106#define PCINIT_XDI_FEATURES 0x1d
107#define PCINIT_QSIG_DIALECT 0x1e
108#define PCINIT_DISABLE_AUTOSPID_FLAG 0x1f
109#define PCINIT_FORCE_VOICE_MAIL_ALERT 0x20
110#define PCINIT_PIAFS_TURNAROUND_FRAMES 0x21
111#define PCINIT_L2_COUNT 0x22
112#define PCINIT_QSIG_FEATURES 0x23
113#define PCINIT_NO_SIGNALLING 0x24
114#define PCINIT_CARD_SN 0x25
115#define PCINIT_CARD_PORT 0x26
116#define PCINIT_ALERTTO 0x27
117#define PCINIT_MODEM_EYE_SETUP 0x28
118#define PCINIT_FAX_V34_OPTIONS 0x29
119/*------------------------------------------------------------------*/
120#define PCINIT_MODEM_GUARD_TONE_NONE 0x00
121#define PCINIT_MODEM_GUARD_TONE_550HZ 0x01
122#define PCINIT_MODEM_GUARD_TONE_1800HZ 0x02
123#define PCINIT_MODEM_GUARD_TONE_CHOICES 0x03
124#define PCINIT_MODEMPROT_DISABLE_V42_V42BIS 0x0001
125#define PCINIT_MODEMPROT_DISABLE_MNP_MNP5 0x0002
126#define PCINIT_MODEMPROT_REQUIRE_PROTOCOL 0x0004
127#define PCINIT_MODEMPROT_DISABLE_V42_DETECT 0x0008
128#define PCINIT_MODEMPROT_DISABLE_COMPRESSION 0x0010
129#define PCINIT_MODEMPROT_REQUIRE_PROTOCOL_V34UP 0x0020
130#define PCINIT_MODEMPROT_NO_PROTOCOL_IF_1200 0x0100
131#define PCINIT_MODEMPROT_BUFFER_IN_V42_DETECT 0x0200
132#define PCINIT_MODEMPROT_DISABLE_V42_SREJ 0x0400
133#define PCINIT_MODEMPROT_DISABLE_MNP3 0x0800
134#define PCINIT_MODEMPROT_DISABLE_MNP4 0x1000
135#define PCINIT_MODEMPROT_DISABLE_MNP10 0x2000
136#define PCINIT_MODEMPROT_NO_PROTOCOL_IF_V22BIS 0x4000
137#define PCINIT_MODEMPROT_NO_PROTOCOL_IF_V32BIS 0x8000
138#define PCINIT_MODEMCONFIG_LEASED_LINE_MODE 0x00000001L
139#define PCINIT_MODEMCONFIG_4_WIRE_OPERATION 0x00000002L
140#define PCINIT_MODEMCONFIG_DISABLE_BUSY_DETECT 0x00000004L
141#define PCINIT_MODEMCONFIG_DISABLE_CALLING_TONE 0x00000008L
142#define PCINIT_MODEMCONFIG_DISABLE_ANSWER_TONE 0x00000010L
143#define PCINIT_MODEMCONFIG_ENABLE_DIAL_TONE_DET 0x00000020L
144#define PCINIT_MODEMCONFIG_USE_POTS_INTERFACE 0x00000040L
145#define PCINIT_MODEMCONFIG_FORCE_RAY_TAYLOR_FAX 0x00000080L
146#define PCINIT_MODEMCONFIG_DISABLE_RETRAIN 0x00000100L
147#define PCINIT_MODEMCONFIG_DISABLE_STEPDOWN 0x00000200L
148#define PCINIT_MODEMCONFIG_DISABLE_SPLIT_SPEED 0x00000400L
149#define PCINIT_MODEMCONFIG_DISABLE_TRELLIS 0x00000800L
150#define PCINIT_MODEMCONFIG_ALLOW_RDL_TEST_LOOP 0x00001000L
151#define PCINIT_MODEMCONFIG_DISABLE_STEPUP 0x00002000L
152#define PCINIT_MODEMCONFIG_DISABLE_FLUSH_TIMER 0x00004000L
153#define PCINIT_MODEMCONFIG_REVERSE_DIRECTION 0x00008000L
154#define PCINIT_MODEMCONFIG_DISABLE_TX_REDUCTION 0x00010000L
155#define PCINIT_MODEMCONFIG_DISABLE_PRECODING 0x00020000L
156#define PCINIT_MODEMCONFIG_DISABLE_PREEMPHASIS 0x00040000L
157#define PCINIT_MODEMCONFIG_DISABLE_SHAPING 0x00080000L
158#define PCINIT_MODEMCONFIG_DISABLE_NONLINEAR_EN 0x00100000L
159#define PCINIT_MODEMCONFIG_DISABLE_MANUALREDUCT 0x00200000L
160#define PCINIT_MODEMCONFIG_DISABLE_16_POINT_TRN 0x00400000L
161#define PCINIT_MODEMCONFIG_DISABLE_2400_SYMBOLS 0x01000000L
162#define PCINIT_MODEMCONFIG_DISABLE_2743_SYMBOLS 0x02000000L
163#define PCINIT_MODEMCONFIG_DISABLE_2800_SYMBOLS 0x04000000L
164#define PCINIT_MODEMCONFIG_DISABLE_3000_SYMBOLS 0x08000000L
165#define PCINIT_MODEMCONFIG_DISABLE_3200_SYMBOLS 0x10000000L
166#define PCINIT_MODEMCONFIG_DISABLE_3429_SYMBOLS 0x20000000L
167#define PCINIT_MODEM_NEGOTIATE_HIGHEST 0x00
168#define PCINIT_MODEM_NEGOTIATE_DISABLED 0x01
169#define PCINIT_MODEM_NEGOTIATE_IN_CLASS 0x02
170#define PCINIT_MODEM_NEGOTIATE_V100 0x03
171#define PCINIT_MODEM_NEGOTIATE_V8 0x04
172#define PCINIT_MODEM_NEGOTIATE_V8BIS 0x05
173#define PCINIT_MODEM_NEGOTIATE_CHOICES 0x06
174#define PCINIT_MODEMMODULATION_DISABLE_V21 0x00000001L
175#define PCINIT_MODEMMODULATION_DISABLE_V23 0x00000002L
176#define PCINIT_MODEMMODULATION_DISABLE_V22 0x00000004L
177#define PCINIT_MODEMMODULATION_DISABLE_V22BIS 0x00000008L
178#define PCINIT_MODEMMODULATION_DISABLE_V32 0x00000010L
179#define PCINIT_MODEMMODULATION_DISABLE_V32BIS 0x00000020L
180#define PCINIT_MODEMMODULATION_DISABLE_V34 0x00000040L
181#define PCINIT_MODEMMODULATION_DISABLE_V90 0x00000080L
182#define PCINIT_MODEMMODULATION_DISABLE_BELL103 0x00000100L
183#define PCINIT_MODEMMODULATION_DISABLE_BELL212A 0x00000200L
184#define PCINIT_MODEMMODULATION_DISABLE_VFC 0x00000400L
185#define PCINIT_MODEMMODULATION_DISABLE_K56FLEX 0x00000800L
186#define PCINIT_MODEMMODULATION_DISABLE_X2 0x00001000L
187#define PCINIT_MODEMMODULATION_ENABLE_V29FDX 0x00010000L
188#define PCINIT_MODEMMODULATION_ENABLE_V33 0x00020000L
189#define PCINIT_MODEMMODULATION_ENABLE_V90A 0x00040000L
190#define PCINIT_MODEM_TRANSMIT_LEVEL_CHOICES 0x10
191#define PCINIT_MODEM_SPEAKER_OFF 0x00
192#define PCINIT_MODEM_SPEAKER_DURING_TRAIN 0x01
193#define PCINIT_MODEM_SPEAKER_TIL_CONNECT 0x02
194#define PCINIT_MODEM_SPEAKER_ALWAYS_ON 0x03
195#define PCINIT_MODEM_SPEAKER_CHOICES 0x04
196#define PCINIT_MODEM_SPEAKER_VOLUME_MIN 0x00
197#define PCINIT_MODEM_SPEAKER_VOLUME_LOW 0x01
198#define PCINIT_MODEM_SPEAKER_VOLUME_HIGH 0x02
199#define PCINIT_MODEM_SPEAKER_VOLUME_MAX 0x03
200#define PCINIT_MODEM_SPEAKER_VOLUME_CHOICES 0x04
201/*------------------------------------------------------------------*/
202#define PCINIT_FAXCONFIG_DISABLE_FINE 0x0001
203#define PCINIT_FAXCONFIG_DISABLE_ECM 0x0002
204#define PCINIT_FAXCONFIG_ECM_64_BYTES 0x0004
205#define PCINIT_FAXCONFIG_DISABLE_2D_CODING 0x0008
206#define PCINIT_FAXCONFIG_DISABLE_T6_CODING 0x0010
207#define PCINIT_FAXCONFIG_DISABLE_UNCOMPR 0x0020
208#define PCINIT_FAXCONFIG_REFUSE_POLLING 0x0040
209#define PCINIT_FAXCONFIG_HIDE_TOTAL_PAGES 0x0080
210#define PCINIT_FAXCONFIG_HIDE_ALL_HEADLINE 0x0100
211#define PCINIT_FAXCONFIG_HIDE_PAGE_INFO 0x0180
212#define PCINIT_FAXCONFIG_HEADLINE_OPTIONS_MASK 0x0180
213#define PCINIT_FAXCONFIG_DISABLE_FEATURE_FALLBACK 0x0200
214#define PCINIT_FAXCONFIG_V34FAX_CONTROL_RATE_1200 0x0800
215#define PCINIT_FAXCONFIG_DISABLE_V34FAX 0x1000
216#define PCINIT_FAXCONFIG_DISABLE_R8_0770_OR_200 0x01
217#define PCINIT_FAXCONFIG_DISABLE_R8_1540 0x02
218#define PCINIT_FAXCONFIG_DISABLE_R16_1540_OR_400 0x04
219#define PCINIT_FAXCONFIG_DISABLE_R4_0385_OR_100 0x08
220#define PCINIT_FAXCONFIG_DISABLE_300_300 0x10
221#define PCINIT_FAXCONFIG_DISABLE_INCH_BASED 0x40
222#define PCINIT_FAXCONFIG_DISABLE_METRIC_BASED 0x80
223#define PCINIT_FAXCONFIG_REC_WIDTH_ISO_A3 0
224#define PCINIT_FAXCONFIG_REC_WIDTH_ISO_B4 1
225#define PCINIT_FAXCONFIG_REC_WIDTH_ISO_A4 2
226#define PCINIT_FAXCONFIG_REC_WIDTH_COUNT 3
227#define PCINIT_FAXCONFIG_REC_LENGTH_UNLIMITED 0
228#define PCINIT_FAXCONFIG_REC_LENGTH_ISO_B4 1
229#define PCINIT_FAXCONFIG_REC_LENGTH_ISO_A4 2
230#define PCINIT_FAXCONFIG_REC_LENGTH_COUNT 3
231#define PCINIT_FAXCONFIG_SCANLINE_TIME_00_00_00 0
232#define PCINIT_FAXCONFIG_SCANLINE_TIME_05_05_05 1
233#define PCINIT_FAXCONFIG_SCANLINE_TIME_10_05_05 2
234#define PCINIT_FAXCONFIG_SCANLINE_TIME_10_10_10 3
235#define PCINIT_FAXCONFIG_SCANLINE_TIME_20_10_10 4
236#define PCINIT_FAXCONFIG_SCANLINE_TIME_20_20_20 5
237#define PCINIT_FAXCONFIG_SCANLINE_TIME_40_20_20 6
238#define PCINIT_FAXCONFIG_SCANLINE_TIME_40_40_40 7
239#define PCINIT_FAXCONFIG_SCANLINE_TIME_RES_8 8
240#define PCINIT_FAXCONFIG_SCANLINE_TIME_RES_9 9
241#define PCINIT_FAXCONFIG_SCANLINE_TIME_RES_10 10
242#define PCINIT_FAXCONFIG_SCANLINE_TIME_10_10_05 11
243#define PCINIT_FAXCONFIG_SCANLINE_TIME_20_10_05 12
244#define PCINIT_FAXCONFIG_SCANLINE_TIME_20_20_10 13
245#define PCINIT_FAXCONFIG_SCANLINE_TIME_40_20_10 14
246#define PCINIT_FAXCONFIG_SCANLINE_TIME_40_40_20 15
247#define PCINIT_FAXCONFIG_SCANLINE_TIME_COUNT 16
248#define PCINIT_FAXCONFIG_DISABLE_TX_REDUCTION 0x00010000L
249#define PCINIT_FAXCONFIG_DISABLE_PRECODING 0x00020000L
250#define PCINIT_FAXCONFIG_DISABLE_PREEMPHASIS 0x00040000L
251#define PCINIT_FAXCONFIG_DISABLE_SHAPING 0x00080000L
252#define PCINIT_FAXCONFIG_DISABLE_NONLINEAR_EN 0x00100000L
253#define PCINIT_FAXCONFIG_DISABLE_MANUALREDUCT 0x00200000L
254#define PCINIT_FAXCONFIG_DISABLE_16_POINT_TRN 0x00400000L
255#define PCINIT_FAXCONFIG_DISABLE_2400_SYMBOLS 0x01000000L
256#define PCINIT_FAXCONFIG_DISABLE_2743_SYMBOLS 0x02000000L
257#define PCINIT_FAXCONFIG_DISABLE_2800_SYMBOLS 0x04000000L
258#define PCINIT_FAXCONFIG_DISABLE_3000_SYMBOLS 0x08000000L
259#define PCINIT_FAXCONFIG_DISABLE_3200_SYMBOLS 0x10000000L
260#define PCINIT_FAXCONFIG_DISABLE_3429_SYMBOLS 0x20000000L
261/*--------------------------------------------------------------------------*/
262#define PCINIT_XDI_CMA_FOR_ALL_NL_PRIMITIVES 0x01
263/*--------------------------------------------------------------------------*/
264#define PCINIT_FPGA_PLX_ACCESS_SUPPORTED 0x01
265/*--------------------------------------------------------------------------*/
266#endif
267/*--------------------------------------------------------------------------*/
diff --git a/drivers/isdn/hardware/eicon/pc_maint.h b/drivers/isdn/hardware/eicon/pc_maint.h
new file mode 100644
index 000000000000..352ab8dafb22
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/pc_maint.h
@@ -0,0 +1,160 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifdef PLATFORM_GT_32BIT
27/* #define POINTER_32BIT byte * __ptr32 */
28#define POINTER_32BIT dword
29#else
30#define POINTER_32BIT byte *
31#endif
32#if !defined(MIPS_SCOM)
33#define BUFFER_SZ 48
34#define MAINT_OFFS 0x380
35#else
36#define BUFFER_SZ 128
37#if defined(PRI)
38#define MAINT_OFFS 0xef00
39#else
40#define MAINT_OFFS 0xff00
41#endif
42#endif
43#define MIPS_BUFFER_SZ 128
44#if defined(PRI)
45#define MIPS_MAINT_OFFS 0xef00
46#else
47#define MIPS_MAINT_OFFS 0xff00
48#endif
49#define LOG 1
50#define MEMR 2
51#define MEMW 3
52#define IOR 4
53#define IOW 5
54#define B1TEST 6
55#define B2TEST 7
56#define BTESTOFF 8
57#define DSIG_STATS 9
58#define B_CH_STATS 10
59#define D_CH_STATS 11
60#define BL1_STATS 12
61#define BL1_STATS_C 13
62#define GET_VERSION 14
63#define OS_STATS 15
64#define XLOG_SET_MASK 16
65#define XLOG_GET_MASK 17
66#define DSP_READ 20
67#define DSP_WRITE 21
68#define OK 0xff
69#define MORE_EVENTS 0xfe
70#define NO_EVENT 1
71struct DSigStruc
72{
73 byte Id;
74 byte u;
75 byte listen;
76 byte active;
77 byte sin[3];
78 byte bc[6];
79 byte llc[6];
80 byte hlc[6];
81 byte oad[20];
82};
83struct BL1Struc {
84 dword cx_b1;
85 dword cx_b2;
86 dword cr_b1;
87 dword cr_b2;
88 dword px_b1;
89 dword px_b2;
90 dword pr_b1;
91 dword pr_b2;
92 word er_b1;
93 word er_b2;
94};
95struct L2Struc {
96 dword XTotal;
97 dword RTotal;
98 word XError;
99 word RError;
100};
101struct OSStruc {
102 dword free_n;
103};
104typedef union
105{
106 struct DSigStruc DSigStats;
107 struct BL1Struc BL1Stats;
108 struct L2Struc L2Stats;
109 struct OSStruc OSStats;
110 byte b[BUFFER_SZ];
111 word w[BUFFER_SZ>>1];
112 word l[BUFFER_SZ>>2]; /* word is wrong, do not use! Use 'd' instead. */
113 dword d[BUFFER_SZ>>2];
114} BUFFER;
115typedef union
116{
117 struct DSigStruc DSigStats;
118 struct BL1Struc BL1Stats;
119 struct L2Struc L2Stats;
120 struct OSStruc OSStats;
121 byte b[MIPS_BUFFER_SZ];
122 word w[MIPS_BUFFER_SZ>>1];
123 word l[BUFFER_SZ>>2]; /* word is wrong, do not use! Use 'd' instead. */
124 dword d[MIPS_BUFFER_SZ>>2];
125} MIPS_BUFFER;
126#if !defined(MIPS_SCOM)
127struct pc_maint
128{
129 byte req;
130 byte rc;
131 POINTER_32BIT mem;
132 short length;
133 word port;
134 byte fill[6];
135 BUFFER data;
136};
137#else
138struct pc_maint
139{
140 byte req;
141 byte rc;
142 byte reserved[2]; /* R3000 alignment ... */
143 POINTER_32BIT mem;
144 short length;
145 word port;
146 byte fill[4]; /* data at offset 16 */
147 BUFFER data;
148};
149#endif
150struct mi_pc_maint
151{
152 byte req;
153 byte rc;
154 byte reserved[2]; /* R3000 alignment ... */
155 POINTER_32BIT mem;
156 short length;
157 word port;
158 byte fill[4]; /* data at offset 16 */
159 MIPS_BUFFER data;
160};
diff --git a/drivers/isdn/hardware/eicon/pkmaint.h b/drivers/isdn/hardware/eicon/pkmaint.h
new file mode 100644
index 000000000000..722f85fe42f6
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/pkmaint.h
@@ -0,0 +1,44 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef __DIVA_XDI_OS_DEPENDENT_PACK_MAIN_ON_BYTE_INC__
27#define __DIVA_XDI_OS_DEPENDENT_PACK_MAIN_ON_BYTE_INC__
28
29
30/*
31 Only one purpose of this compiler dependent file to pack
32 structures, described in pc_maint.h so that no padding
33 will be included.
34
35 With microsoft compile it is done by "pshpack1.h" and
36 after is restored by "poppack.h"
37 */
38
39
40#include "pc_maint.h"
41
42
43#endif
44
diff --git a/drivers/isdn/hardware/eicon/platform.h b/drivers/isdn/hardware/eicon/platform.h
new file mode 100644
index 000000000000..12b8ff29e976
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/platform.h
@@ -0,0 +1,394 @@
1/* $Id: platform.h,v 1.37.4.6 2005/01/31 12:22:20 armin Exp $
2 *
3 * platform.h
4 *
5 *
6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7 * Copyright 2000 Eicon Networks
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 */
12
13
14#ifndef __PLATFORM_H__
15#define __PLATFORM_H__
16
17#if !defined(DIVA_BUILD)
18#define DIVA_BUILD "local"
19#endif
20
21#include <linux/config.h>
22#include <linux/module.h>
23#include <linux/init.h>
24#include <linux/kernel.h>
25#include <linux/sched.h>
26#include <linux/skbuff.h>
27#include <linux/vmalloc.h>
28#include <linux/proc_fs.h>
29#include <linux/interrupt.h>
30#include <linux/smp_lock.h>
31#include <linux/delay.h>
32#include <linux/list.h>
33#include <asm/types.h>
34#include <asm/io.h>
35
36#include "cardtype.h"
37
38/* activate debuglib for modules only */
39#ifndef MODULE
40#define DIVA_NO_DEBUGLIB
41#endif
42
43#define DIVA_INIT_FUNCTION __init
44#define DIVA_EXIT_FUNCTION __exit
45
46#define DIVA_USER_MODE_CARD_CONFIG 1
47#define USE_EXTENDED_DEBUGS 1
48
49#define MAX_ADAPTER 32
50
51#define DIVA_ISTREAM 1
52
53#define MEMORY_SPACE_TYPE 0
54#define PORT_SPACE_TYPE 1
55
56
57#include <linux/string.h>
58
59#ifndef byte
60#define byte u8
61#endif
62
63#ifndef word
64#define word u16
65#endif
66
67#ifndef dword
68#define dword u32
69#endif
70
71#ifndef qword
72#define qword u64
73#endif
74
75#ifndef TRUE
76#define TRUE 1
77#endif
78
79#ifndef FALSE
80#define FALSE 0
81#endif
82
83#ifndef NULL
84#define NULL ((void *) 0)
85#endif
86
87#ifndef MIN
88#define MIN(a,b) ((a)>(b) ? (b) : (a))
89#endif
90
91#ifndef MAX
92#define MAX(a,b) ((a)>(b) ? (a) : (b))
93#endif
94
95#ifndef far
96#define far
97#endif
98
99#ifndef _pascal
100#define _pascal
101#endif
102
103#ifndef _loadds
104#define _loadds
105#endif
106
107#ifndef _cdecl
108#define _cdecl
109#endif
110
111#define MEM_TYPE_RAM 0
112#define MEM_TYPE_PORT 1
113#define MEM_TYPE_PROM 2
114#define MEM_TYPE_CTLREG 3
115#define MEM_TYPE_RESET 4
116#define MEM_TYPE_CFG 5
117#define MEM_TYPE_ADDRESS 6
118#define MEM_TYPE_CONFIG 7
119#define MEM_TYPE_CONTROL 8
120
121#define MAX_MEM_TYPE 10
122
123#define DIVA_OS_MEM_ATTACH_RAM(a) ((a)->ram)
124#define DIVA_OS_MEM_ATTACH_PORT(a) ((a)->port)
125#define DIVA_OS_MEM_ATTACH_PROM(a) ((a)->prom)
126#define DIVA_OS_MEM_ATTACH_CTLREG(a) ((a)->ctlReg)
127#define DIVA_OS_MEM_ATTACH_RESET(a) ((a)->reset)
128#define DIVA_OS_MEM_ATTACH_CFG(a) ((a)->cfg)
129#define DIVA_OS_MEM_ATTACH_ADDRESS(a) ((a)->Address)
130#define DIVA_OS_MEM_ATTACH_CONFIG(a) ((a)->Config)
131#define DIVA_OS_MEM_ATTACH_CONTROL(a) ((a)->Control)
132
133#define DIVA_OS_MEM_DETACH_RAM(a, x) do { } while(0)
134#define DIVA_OS_MEM_DETACH_PORT(a, x) do { } while(0)
135#define DIVA_OS_MEM_DETACH_PROM(a, x) do { } while(0)
136#define DIVA_OS_MEM_DETACH_CTLREG(a, x) do { } while(0)
137#define DIVA_OS_MEM_DETACH_RESET(a, x) do { } while(0)
138#define DIVA_OS_MEM_DETACH_CFG(a, x) do { } while(0)
139#define DIVA_OS_MEM_DETACH_ADDRESS(a, x) do { } while(0)
140#define DIVA_OS_MEM_DETACH_CONFIG(a, x) do { } while(0)
141#define DIVA_OS_MEM_DETACH_CONTROL(a, x) do { } while(0)
142
143#if !defined(DIM)
144#define DIM(array) (sizeof (array)/sizeof ((array)[0]))
145#endif
146
147#define DIVA_INVALID_FILE_HANDLE ((dword)(-1))
148
149#define DIVAS_CONTAINING_RECORD(address, type, field) \
150 ((type *)((char*)(address) - (char*)(&((type *)0)->field)))
151
152extern int sprintf(char *, const char*, ...);
153
154typedef void* LIST_ENTRY;
155
156typedef char DEVICE_NAME[64];
157typedef struct _ISDN_ADAPTER ISDN_ADAPTER;
158typedef struct _ISDN_ADAPTER* PISDN_ADAPTER;
159
160typedef void (* DIVA_DI_PRINTF) (unsigned char *, ...);
161#include "debuglib.h"
162
163#define dtrc(p) DBG_PRV0(p)
164#define dbug(a,p) DBG_PRV1(p)
165
166
167typedef struct e_info_s E_INFO ;
168
169typedef char diva_os_dependent_devica_name_t[64];
170typedef void* PDEVICE_OBJECT;
171
172struct _diva_os_soft_isr;
173struct _diva_os_timer;
174struct _ISDN_ADAPTER;
175
176void diva_log_info(unsigned char *, ...);
177
178/*
179** XDI DIDD Interface
180*/
181void diva_xdi_didd_register_adapter (int card);
182void diva_xdi_didd_remove_adapter (int card);
183
184/*
185** memory allocation
186*/
187static __inline__ void* diva_os_malloc (unsigned long flags, unsigned long size)
188{
189 void *ret = NULL;
190
191 if (size) {
192 ret = (void *) vmalloc((unsigned int) size);
193 }
194 return (ret);
195}
196static __inline__ void diva_os_free (unsigned long flags, void* ptr)
197{
198 vfree(ptr);
199}
200
201/*
202** use skbuffs for message buffer
203*/
204typedef struct sk_buff diva_os_message_buffer_s;
205diva_os_message_buffer_s *diva_os_alloc_message_buffer(unsigned long size, void **data_buf);
206void diva_os_free_message_buffer(diva_os_message_buffer_s *dmb);
207#define DIVA_MESSAGE_BUFFER_LEN(x) x->len
208#define DIVA_MESSAGE_BUFFER_DATA(x) x->data
209
210/*
211** mSeconds waiting
212*/
213static __inline__ void diva_os_sleep(dword mSec)
214{
215 msleep(mSec);
216}
217static __inline__ void diva_os_wait(dword mSec)
218{
219 mdelay(mSec);
220}
221
222/*
223** PCI Configuration space access
224*/
225void PCIwrite (byte bus, byte func, int offset, void* data, int length, void* pci_dev_handle);
226void PCIread (byte bus, byte func, int offset, void* data, int length, void* pci_dev_handle);
227
228/*
229** I/O Port utilities
230*/
231int diva_os_register_io_port (void *adapter, int register, unsigned long port,
232 unsigned long length, const char* name, int id);
233/*
234** I/O port access abstraction
235*/
236byte inpp (void __iomem *);
237word inppw (void __iomem *);
238void inppw_buffer (void __iomem *, void*, int);
239void outppw (void __iomem *, word);
240void outppw_buffer (void __iomem * , void*, int);
241void outpp (void __iomem *, word);
242
243/*
244** IRQ
245*/
246typedef struct _diva_os_adapter_irq_info {
247 byte irq_nr;
248 int registered;
249 char irq_name[24];
250} diva_os_adapter_irq_info_t;
251int diva_os_register_irq (void* context, byte irq, const char* name);
252void diva_os_remove_irq (void* context, byte irq);
253
254#define diva_os_in_irq() in_irq()
255
256/*
257** Spin Lock framework
258*/
259typedef long diva_os_spin_lock_magic_t;
260typedef spinlock_t diva_os_spin_lock_t;
261static __inline__ int diva_os_initialize_spin_lock (spinlock_t *lock, void * unused) { \
262 spin_lock_init (lock); return(0); }
263static __inline__ void diva_os_enter_spin_lock (diva_os_spin_lock_t* a, \
264 diva_os_spin_lock_magic_t* old_irql, \
265 void* dbg) { spin_lock_bh(a); }
266static __inline__ void diva_os_leave_spin_lock (diva_os_spin_lock_t* a, \
267 diva_os_spin_lock_magic_t* old_irql, \
268 void* dbg) { spin_unlock_bh(a); }
269
270#define diva_os_destroy_spin_lock(a,b) do { } while(0)
271
272/*
273** Deffered processing framework
274*/
275typedef int (*diva_os_isr_callback_t)(struct _ISDN_ADAPTER*);
276typedef void (*diva_os_soft_isr_callback_t)(struct _diva_os_soft_isr* psoft_isr, void* context);
277
278typedef struct _diva_os_soft_isr {
279 void* object;
280 diva_os_soft_isr_callback_t callback;
281 void* callback_context;
282 char dpc_thread_name[24];
283} diva_os_soft_isr_t;
284
285int diva_os_initialize_soft_isr (diva_os_soft_isr_t* psoft_isr, diva_os_soft_isr_callback_t callback, void* callback_context);
286int diva_os_schedule_soft_isr (diva_os_soft_isr_t* psoft_isr);
287int diva_os_cancel_soft_isr (diva_os_soft_isr_t* psoft_isr);
288void diva_os_remove_soft_isr (diva_os_soft_isr_t* psoft_isr);
289
290/*
291 Get time service
292 */
293void diva_os_get_time (dword* sec, dword* usec);
294
295/*
296** atomic operation, fake because we use threads
297*/
298typedef int diva_os_atomic_t;
299static diva_os_atomic_t __inline__
300diva_os_atomic_increment(diva_os_atomic_t* pv)
301{
302 *pv += 1;
303 return (*pv);
304}
305static diva_os_atomic_t __inline__
306diva_os_atomic_decrement(diva_os_atomic_t* pv)
307{
308 *pv -= 1;
309 return (*pv);
310}
311
312/*
313** CAPI SECTION
314*/
315#define NO_CORNETN
316#define IMPLEMENT_DTMF 1
317#define IMPLEMENT_ECHO_CANCELLER 1
318#define IMPLEMENT_RTP 1
319#define IMPLEMENT_T38 1
320#define IMPLEMENT_FAX_SUB_SEP_PWD 1
321#define IMPLEMENT_V18 1
322#define IMPLEMENT_DTMF_TONE 1
323#define IMPLEMENT_PIAFS 1
324#define IMPLEMENT_FAX_PAPER_FORMATS 1
325#define IMPLEMENT_VOWN 1
326#define IMPLEMENT_CAPIDTMF 1
327#define IMPLEMENT_FAX_NONSTANDARD 1
328#define VSWITCH_SUPPORT 1
329
330#define IMPLEMENT_MARKED_OK_AFTER_FC 1
331
332#define DIVA_IDI_RX_DMA 1
333
334/*
335** endian macros
336**
337** If only... In some cases we did use them for endianness conversion;
338** unfortunately, other uses were real iomem accesses.
339*/
340#define READ_BYTE(addr) readb(addr)
341#define READ_WORD(addr) readw(addr)
342#define READ_DWORD(addr) readl(addr)
343
344#define WRITE_BYTE(addr,v) writeb(v,addr)
345#define WRITE_WORD(addr,v) writew(v,addr)
346#define WRITE_DWORD(addr,v) writel(v,addr)
347
348static inline __u16 GET_WORD(void *addr)
349{
350 return le16_to_cpu(*(__le16 *)addr);
351}
352static inline __u32 GET_DWORD(void *addr)
353{
354 return le32_to_cpu(*(__le32 *)addr);
355}
356static inline void PUT_WORD(void *addr, __u16 v)
357{
358 *(__le16 *)addr = cpu_to_le16(v);
359}
360static inline void PUT_DWORD(void *addr, __u32 v)
361{
362 *(__le32 *)addr = cpu_to_le32(v);
363}
364
365/*
366** 32/64 bit macors
367*/
368#ifdef BITS_PER_LONG
369 #if BITS_PER_LONG > 32
370 #define PLATFORM_GT_32BIT
371 #define ULongToPtr(x) (void *)(unsigned long)(x)
372 #endif
373#endif
374
375/*
376** undef os definitions of macros we use
377*/
378#undef ID_MASK
379#undef N_DATA
380#undef ADDR
381
382/*
383** dump file
384*/
385#define diva_os_dump_file_t char
386#define diva_os_board_trace_t char
387#define diva_os_dump_file(__x__) do { } while(0)
388
389/*
390** size of internal arrays
391*/
392#define MAX_DESCRIPTORS 64
393
394#endif /* __PLATFORM_H__ */
diff --git a/drivers/isdn/hardware/eicon/pr_pc.h b/drivers/isdn/hardware/eicon/pr_pc.h
new file mode 100644
index 000000000000..bf49a5af567f
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/pr_pc.h
@@ -0,0 +1,76 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26struct pr_ram {
27 word NextReq; /* pointer to next Req Buffer */
28 word NextRc; /* pointer to next Rc Buffer */
29 word NextInd; /* pointer to next Ind Buffer */
30 byte ReqInput; /* number of Req Buffers sent */
31 byte ReqOutput; /* number of Req Buffers returned */
32 byte ReqReserved; /* number of Req Buffers reserved */
33 byte Int; /* ISDN-P interrupt */
34 byte XLock; /* Lock field for arbitration */
35 byte RcOutput; /* number of Rc buffers received */
36 byte IndOutput; /* number of Ind buffers received */
37 byte IMask; /* Interrupt Mask Flag */
38 byte Reserved1[2]; /* reserved field, do not use */
39 byte ReadyInt; /* request field for ready interrupt */
40 byte Reserved2[12]; /* reserved field, do not use */
41 byte InterfaceType; /* interface type 1=16K interface */
42 word Signature; /* ISDN-P initialized indication */
43 byte B[1]; /* buffer space for Req,Ind and Rc */
44};
45typedef struct {
46 word next;
47 byte Req;
48 byte ReqId;
49 byte ReqCh;
50 byte Reserved1;
51 word Reference;
52 byte Reserved[8];
53 PBUFFER XBuffer;
54} REQ;
55typedef struct {
56 word next;
57 byte Rc;
58 byte RcId;
59 byte RcCh;
60 byte Reserved1;
61 word Reference;
62 byte Reserved2[8];
63} RC;
64typedef struct {
65 word next;
66 byte Ind;
67 byte IndId;
68 byte IndCh;
69 byte MInd;
70 word MLength;
71 word Reference;
72 byte RNR;
73 byte Reserved;
74 dword Ack;
75 PBUFFER RBuffer;
76} IND;
diff --git a/drivers/isdn/hardware/eicon/s_4bri.c b/drivers/isdn/hardware/eicon/s_4bri.c
new file mode 100644
index 000000000000..25c5d7feb838
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/s_4bri.c
@@ -0,0 +1,510 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#include "platform.h"
27#include "di_defs.h"
28#include "pc.h"
29#include "pr_pc.h"
30#include "di.h"
31#include "mi_pc.h"
32#include "pc_maint.h"
33#include "divasync.h"
34#include "pc_init.h"
35#include "io.h"
36#include "helpers.h"
37#include "dsrv4bri.h"
38#include "dsp_defs.h"
39#include "sdp_hdr.h"
40
41/*****************************************************************************/
42#define MAX_XLOG_SIZE (64 * 1024)
43
44/* --------------------------------------------------------------------------
45 Recovery XLOG from QBRI Card
46 -------------------------------------------------------------------------- */
47static void qBri_cpu_trapped (PISDN_ADAPTER IoAdapter) {
48 byte __iomem *base ;
49 word *Xlog ;
50 dword regs[4], TrapID, offset, size ;
51 Xdesc xlogDesc ;
52 int factor = (IoAdapter->tasks == 1) ? 1 : 2;
53
54/*
55 * check for trapped MIPS 46xx CPU, dump exception frame
56 */
57
58 base = DIVA_OS_MEM_ATTACH_CONTROL(IoAdapter);
59 offset = IoAdapter->ControllerNumber * (IoAdapter->MemorySize >> factor) ;
60
61 TrapID = READ_DWORD(&base[0x80]) ;
62
63 if ( (TrapID == 0x99999999) || (TrapID == 0x99999901) )
64 {
65 dump_trap_frame (IoAdapter, &base[0x90]) ;
66 IoAdapter->trapped = 1 ;
67 }
68
69 regs[0] = READ_DWORD((base + offset) + 0x70);
70 regs[1] = READ_DWORD((base + offset) + 0x74);
71 regs[2] = READ_DWORD((base + offset) + 0x78);
72 regs[3] = READ_DWORD((base + offset) + 0x7c);
73 regs[0] &= IoAdapter->MemorySize - 1 ;
74
75 if ( (regs[0] >= offset)
76 && (regs[0] < offset + (IoAdapter->MemorySize >> factor) - 1) )
77 {
78 if ( !(Xlog = (word *)diva_os_malloc (0, MAX_XLOG_SIZE)) ) {
79 DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base);
80 return ;
81 }
82
83 size = offset + (IoAdapter->MemorySize >> factor) - regs[0] ;
84 if ( size > MAX_XLOG_SIZE )
85 size = MAX_XLOG_SIZE ;
86 memcpy_fromio (Xlog, &base[regs[0]], size) ;
87 xlogDesc.buf = Xlog ;
88 xlogDesc.cnt = READ_WORD(&base[regs[1] & (IoAdapter->MemorySize - 1)]) ;
89 xlogDesc.out = READ_WORD(&base[regs[2] & (IoAdapter->MemorySize - 1)]) ;
90 dump_xlog_buffer (IoAdapter, &xlogDesc) ;
91 diva_os_free (0, Xlog) ;
92 IoAdapter->trapped = 2 ;
93 }
94 DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base);
95}
96
97/* --------------------------------------------------------------------------
98 Reset QBRI Hardware
99 -------------------------------------------------------------------------- */
100static void reset_qBri_hardware (PISDN_ADAPTER IoAdapter) {
101 word volatile __iomem *qBriReset ;
102 byte volatile __iomem *qBriCntrl ;
103 byte volatile __iomem *p ;
104
105 qBriReset = (word volatile __iomem *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter);
106 WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_SOFT_RESET) ;
107 diva_os_wait (1) ;
108 WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_SOFT_RESET) ;
109 diva_os_wait (1);
110 WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_RELOAD_EEPROM) ;
111 diva_os_wait (1) ;
112 WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_RELOAD_EEPROM) ;
113 diva_os_wait (1);
114 DIVA_OS_MEM_DETACH_PROM(IoAdapter, qBriReset);
115
116 qBriCntrl = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
117 p = &qBriCntrl[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)];
118 WRITE_DWORD(p, 0) ;
119 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, qBriCntrl);
120
121 DBG_TRC(("resetted board @ reset addr 0x%08lx", qBriReset))
122 DBG_TRC(("resetted board @ cntrl addr 0x%08lx", p))
123}
124
125/* --------------------------------------------------------------------------
126 Start Card CPU
127 -------------------------------------------------------------------------- */
128void start_qBri_hardware (PISDN_ADAPTER IoAdapter) {
129 byte volatile __iomem *qBriReset ;
130 byte volatile __iomem *p ;
131
132 p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
133 qBriReset = &p[(DIVA_4BRI_REVISION(IoAdapter)) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)];
134 WRITE_DWORD(qBriReset, MQ_RISC_COLD_RESET_MASK) ;
135 diva_os_wait (2) ;
136 WRITE_DWORD(qBriReset, MQ_RISC_WARM_RESET_MASK | MQ_RISC_COLD_RESET_MASK) ;
137 diva_os_wait (10) ;
138 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
139
140 DBG_TRC(("started processor @ addr 0x%08lx", qBriReset))
141}
142
143/* --------------------------------------------------------------------------
144 Stop Card CPU
145 -------------------------------------------------------------------------- */
146static void stop_qBri_hardware (PISDN_ADAPTER IoAdapter) {
147 byte volatile __iomem *p ;
148 dword volatile __iomem *qBriReset ;
149 dword volatile __iomem *qBriIrq ;
150 dword volatile __iomem *qBriIsacDspReset ;
151 int rev2 = DIVA_4BRI_REVISION(IoAdapter);
152 int reset_offset = rev2 ? (MQ2_BREG_RISC) : (MQ_BREG_RISC);
153 int irq_offset = rev2 ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST);
154 int hw_offset = rev2 ? (MQ2_ISAC_DSP_RESET) : (MQ_ISAC_DSP_RESET);
155
156 if ( IoAdapter->ControllerNumber > 0 )
157 return ;
158 p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
159 qBriReset = (dword volatile __iomem *)&p[reset_offset];
160 qBriIsacDspReset = (dword volatile __iomem *)&p[hw_offset];
161/*
162 * clear interrupt line (reset Local Interrupt Test Register)
163 */
164 WRITE_DWORD(qBriReset, 0) ;
165 WRITE_DWORD(qBriIsacDspReset, 0) ;
166 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
167
168 p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
169 WRITE_BYTE(&p[PLX9054_INTCSR], 0x00); /* disable PCI interrupts */
170 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
171
172 p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
173 qBriIrq = (dword volatile __iomem *)&p[irq_offset];
174 WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ;
175 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
176
177 DBG_TRC(("stopped processor @ addr 0x%08lx", qBriReset))
178
179}
180
181/* --------------------------------------------------------------------------
182 FPGA download
183 -------------------------------------------------------------------------- */
184#define FPGA_NAME_OFFSET 0x10
185
186static byte * qBri_check_FPGAsrc (PISDN_ADAPTER IoAdapter, char *FileName,
187 dword *Length, dword *code) {
188 byte *File ;
189 char *fpgaFile, *fpgaType, *fpgaDate, *fpgaTime ;
190 dword fpgaFlen, fpgaTlen, fpgaDlen, cnt, year, i ;
191
192 if (!(File = (byte *)xdiLoadFile (FileName, Length, 0))) {
193 return (NULL) ;
194 }
195/*
196 * scan file until FF and put id string into buffer
197 */
198 for ( i = 0 ; File[i] != 0xff ; )
199 {
200 if ( ++i >= *Length )
201 {
202 DBG_FTL(("FPGA download: start of data header not found"))
203 xdiFreeFile (File) ;
204 return (NULL) ;
205 }
206 }
207 *code = i++ ;
208
209 if ( (File[i] & 0xF0) != 0x20 )
210 {
211 DBG_FTL(("FPGA download: data header corrupted"))
212 xdiFreeFile (File) ;
213 return (NULL) ;
214 }
215 fpgaFlen = (dword) File[FPGA_NAME_OFFSET - 1] ;
216 if ( fpgaFlen == 0 )
217 fpgaFlen = 12 ;
218 fpgaFile = (char *)&File[FPGA_NAME_OFFSET] ;
219 fpgaTlen = (dword) fpgaFile[fpgaFlen + 2] ;
220 if ( fpgaTlen == 0 )
221 fpgaTlen = 10 ;
222 fpgaType = (char *)&fpgaFile[fpgaFlen + 3] ;
223 fpgaDlen = (dword) fpgaType[fpgaTlen + 2] ;
224 if ( fpgaDlen == 0 )
225 fpgaDlen = 11 ;
226 fpgaDate = (char *)&fpgaType[fpgaTlen + 3] ;
227 fpgaTime = (char *)&fpgaDate[fpgaDlen + 3] ;
228 cnt = (dword)(((File[ i ] & 0x0F) << 20) + (File[i + 1] << 12)
229 + (File[i + 2] << 4) + (File[i + 3] >> 4)) ;
230
231 if ( (dword)(i + (cnt / 8)) > *Length )
232 {
233 DBG_FTL(("FPGA download: '%s' file too small (%ld < %ld)",
234 FileName, *Length, code + ((cnt + 7) / 8) ))
235 xdiFreeFile (File) ;
236 return (NULL) ;
237 }
238 i = 0 ;
239 do
240 {
241 while ( (fpgaDate[i] != '\0')
242 && ((fpgaDate[i] < '0') || (fpgaDate[i] > '9')) )
243 {
244 i++;
245 }
246 year = 0 ;
247 while ( (fpgaDate[i] >= '0') && (fpgaDate[i] <= '9') )
248 year = year * 10 + (fpgaDate[i++] - '0') ;
249 } while ( (year < 2000) && (fpgaDate[i] != '\0') );
250
251 switch (IoAdapter->cardType) {
252 case CARDTYPE_DIVASRV_B_2F_PCI:
253 break;
254
255 default:
256 if ( year >= 2001 ) {
257 IoAdapter->fpga_features |= PCINIT_FPGA_PLX_ACCESS_SUPPORTED ;
258 }
259 }
260
261 DBG_LOG(("FPGA[%s] file %s (%s %s) len %d",
262 fpgaType, fpgaFile, fpgaDate, fpgaTime, cnt))
263 return (File) ;
264}
265
266/******************************************************************************/
267
268#define FPGA_PROG 0x0001 /* PROG enable low */
269#define FPGA_BUSY 0x0002 /* BUSY high, DONE low */
270#define FPGA_CS 0x000C /* Enable I/O pins */
271#define FPGA_CCLK 0x0100
272#define FPGA_DOUT 0x0400
273#define FPGA_DIN FPGA_DOUT /* bidirectional I/O */
274
275int qBri_FPGA_download (PISDN_ADAPTER IoAdapter) {
276 int bit ;
277 byte *File ;
278 dword code, FileLength ;
279 word volatile __iomem *addr = (word volatile __iomem *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter);
280 word val, baseval = FPGA_CS | FPGA_PROG ;
281
282
283
284 if (DIVA_4BRI_REVISION(IoAdapter))
285 {
286 char* name;
287
288 switch (IoAdapter->cardType) {
289 case CARDTYPE_DIVASRV_B_2F_PCI:
290 name = "dsbri2f.bit";
291 break;
292
293 case CARDTYPE_DIVASRV_B_2M_V2_PCI:
294 case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
295 name = "dsbri2m.bit";
296 break;
297
298 default:
299 name = "ds4bri2.bit";
300 }
301
302 File = qBri_check_FPGAsrc (IoAdapter, name,
303 &FileLength, &code);
304 }
305 else
306 {
307 File = qBri_check_FPGAsrc (IoAdapter, "ds4bri.bit",
308 &FileLength, &code) ;
309 }
310 if ( !File ) {
311 DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
312 return (0) ;
313 }
314/*
315 * prepare download, pulse PROGRAM pin down.
316 */
317 WRITE_WORD(addr, baseval & ~FPGA_PROG) ; /* PROGRAM low pulse */
318 WRITE_WORD(addr, baseval) ; /* release */
319 diva_os_wait (50) ; /* wait until FPGA finished internal memory clear */
320/*
321 * check done pin, must be low
322 */
323 if ( READ_WORD(addr) & FPGA_BUSY )
324 {
325 DBG_FTL(("FPGA download: acknowledge for FPGA memory clear missing"))
326 xdiFreeFile (File) ;
327 DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
328 return (0) ;
329 }
330/*
331 * put data onto the FPGA
332 */
333 while ( code < FileLength )
334 {
335 val = ((word)File[code++]) << 3 ;
336
337 for ( bit = 8 ; bit-- > 0 ; val <<= 1 ) /* put byte onto FPGA */
338 {
339 baseval &= ~FPGA_DOUT ; /* clr data bit */
340 baseval |= (val & FPGA_DOUT) ; /* copy data bit */
341 WRITE_WORD(addr, baseval) ;
342 WRITE_WORD(addr, baseval | FPGA_CCLK) ; /* set CCLK hi */
343 WRITE_WORD(addr, baseval | FPGA_CCLK) ; /* set CCLK hi */
344 WRITE_WORD(addr, baseval) ; /* set CCLK lo */
345 }
346 }
347 xdiFreeFile (File) ;
348 diva_os_wait (100) ;
349 val = READ_WORD(addr) ;
350
351 DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
352
353 if ( !(val & FPGA_BUSY) )
354 {
355 DBG_FTL(("FPGA download: chip remains in busy state (0x%04x)", val))
356 return (0) ;
357 }
358
359 return (1) ;
360}
361
362static int load_qBri_hardware (PISDN_ADAPTER IoAdapter) {
363 return (0);
364}
365
366/* --------------------------------------------------------------------------
367 Card ISR
368 -------------------------------------------------------------------------- */
369static int qBri_ISR (struct _ISDN_ADAPTER* IoAdapter) {
370 dword volatile __iomem *qBriIrq ;
371
372 PADAPTER_LIST_ENTRY QuadroList = IoAdapter->QuadroList ;
373
374 word i ;
375 int serviced = 0 ;
376 byte __iomem *p;
377
378 p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
379
380 if ( !(READ_BYTE(&p[PLX9054_INTCSR]) & 0x80) ) {
381 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
382 return (0) ;
383 }
384 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
385
386/*
387 * clear interrupt line (reset Local Interrupt Test Register)
388 */
389 p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
390 qBriIrq = (dword volatile __iomem *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST)]);
391 WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ;
392 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
393
394 for ( i = 0 ; i < IoAdapter->tasks; ++i )
395 {
396 IoAdapter = QuadroList->QuadroAdapter[i] ;
397
398 if ( IoAdapter && IoAdapter->Initialized
399 && IoAdapter->tst_irq (&IoAdapter->a) )
400 {
401 IoAdapter->IrqCount++ ;
402 serviced = 1 ;
403 diva_os_schedule_soft_isr (&IoAdapter->isr_soft_isr);
404 }
405 }
406
407 return (serviced) ;
408}
409
410/* --------------------------------------------------------------------------
411 Does disable the interrupt on the card
412 -------------------------------------------------------------------------- */
413static void disable_qBri_interrupt (PISDN_ADAPTER IoAdapter) {
414 dword volatile __iomem *qBriIrq ;
415 byte __iomem *p;
416
417 if ( IoAdapter->ControllerNumber > 0 )
418 return ;
419/*
420 * clear interrupt line (reset Local Interrupt Test Register)
421 */
422 p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
423 WRITE_BYTE(&p[PLX9054_INTCSR], 0x00); /* disable PCI interrupts */
424 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
425
426 p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
427 qBriIrq = (dword volatile __iomem *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST)]);
428 WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ;
429 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
430}
431
432/* --------------------------------------------------------------------------
433 Install Adapter Entry Points
434 -------------------------------------------------------------------------- */
435static void set_common_qBri_functions (PISDN_ADAPTER IoAdapter) {
436 ADAPTER *a;
437
438 a = &IoAdapter->a ;
439
440 a->ram_in = mem_in ;
441 a->ram_inw = mem_inw ;
442 a->ram_in_buffer = mem_in_buffer ;
443 a->ram_look_ahead = mem_look_ahead ;
444 a->ram_out = mem_out ;
445 a->ram_outw = mem_outw ;
446 a->ram_out_buffer = mem_out_buffer ;
447 a->ram_inc = mem_inc ;
448
449 IoAdapter->out = pr_out ;
450 IoAdapter->dpc = pr_dpc ;
451 IoAdapter->tst_irq = scom_test_int ;
452 IoAdapter->clr_irq = scom_clear_int ;
453 IoAdapter->pcm = (struct pc_maint *)MIPS_MAINT_OFFS ;
454
455 IoAdapter->load = load_qBri_hardware ;
456
457 IoAdapter->disIrq = disable_qBri_interrupt ;
458 IoAdapter->rstFnc = reset_qBri_hardware ;
459 IoAdapter->stop = stop_qBri_hardware ;
460 IoAdapter->trapFnc = qBri_cpu_trapped ;
461
462 IoAdapter->diva_isr_handler = qBri_ISR;
463
464 IoAdapter->a.io = (void*)IoAdapter ;
465}
466
467static void set_qBri_functions (PISDN_ADAPTER IoAdapter) {
468 if (!IoAdapter->tasks) {
469 IoAdapter->tasks = MQ_INSTANCE_COUNT;
470 }
471 IoAdapter->MemorySize = MQ_MEMORY_SIZE ;
472 set_common_qBri_functions (IoAdapter) ;
473 diva_os_set_qBri_functions (IoAdapter) ;
474}
475
476static void set_qBri2_functions (PISDN_ADAPTER IoAdapter) {
477 if (!IoAdapter->tasks) {
478 IoAdapter->tasks = MQ_INSTANCE_COUNT;
479 }
480 IoAdapter->MemorySize = (IoAdapter->tasks == 1) ? BRI2_MEMORY_SIZE : MQ2_MEMORY_SIZE;
481 set_common_qBri_functions (IoAdapter) ;
482 diva_os_set_qBri2_functions (IoAdapter) ;
483}
484
485/******************************************************************************/
486
487void prepare_qBri_functions (PISDN_ADAPTER IoAdapter) {
488
489 set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[0]) ;
490 set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[1]) ;
491 set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[2]) ;
492 set_qBri_functions (IoAdapter->QuadroList->QuadroAdapter[3]) ;
493
494}
495
496void prepare_qBri2_functions (PISDN_ADAPTER IoAdapter) {
497 if (!IoAdapter->tasks) {
498 IoAdapter->tasks = MQ_INSTANCE_COUNT;
499 }
500
501 set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[0]) ;
502 if (IoAdapter->tasks > 1) {
503 set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[1]) ;
504 set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[2]) ;
505 set_qBri2_functions (IoAdapter->QuadroList->QuadroAdapter[3]) ;
506 }
507
508}
509
510/* -------------------------------------------------------------------------- */
diff --git a/drivers/isdn/hardware/eicon/s_bri.c b/drivers/isdn/hardware/eicon/s_bri.c
new file mode 100644
index 000000000000..5c87552e8c08
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/s_bri.c
@@ -0,0 +1,191 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#include "platform.h"
27#include "di_defs.h"
28#include "pc.h"
29#include "pr_pc.h"
30#include "di.h"
31#include "mi_pc.h"
32#include "pc_maint.h"
33#include "divasync.h"
34#include "io.h"
35#include "helpers.h"
36#include "dsrv_bri.h"
37#include "dsp_defs.h"
38/*****************************************************************************/
39#define MAX_XLOG_SIZE (64 * 1024)
40/* --------------------------------------------------------------------------
41 Investigate card state, recovery trace buffer
42 -------------------------------------------------------------------------- */
43static void bri_cpu_trapped (PISDN_ADAPTER IoAdapter) {
44 byte __iomem *addrHi, *addrLo, *ioaddr ;
45 word *Xlog ;
46 dword regs[4], i, size ;
47 Xdesc xlogDesc ;
48 byte __iomem *Port;
49/*
50 * first read pointers and trap frame
51 */
52 if ( !(Xlog = (word *)diva_os_malloc (0, MAX_XLOG_SIZE)) )
53 return ;
54 Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter);
55 addrHi = Port + ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH) ;
56 addrLo = Port + ADDR ;
57 ioaddr = Port + DATA ;
58 outpp (addrHi, 0) ;
59 outppw (addrLo, 0) ;
60 for ( i = 0 ; i < 0x100 ; Xlog[i++] = inppw(ioaddr) ) ;
61/*
62 * check for trapped MIPS 3xxx CPU, dump only exception frame
63 */
64 if ( GET_DWORD(&Xlog[0x80 / sizeof(Xlog[0])]) == 0x99999999 )
65 {
66 dump_trap_frame (IoAdapter, &((byte *)Xlog)[0x90]) ;
67 IoAdapter->trapped = 1 ;
68 }
69 regs[0] = GET_DWORD(&((byte *)Xlog)[0x70]);
70 regs[1] = GET_DWORD(&((byte *)Xlog)[0x74]);
71 regs[2] = GET_DWORD(&((byte *)Xlog)[0x78]);
72 regs[3] = GET_DWORD(&((byte *)Xlog)[0x7c]);
73 outpp (addrHi, (regs[1] >> 16) & 0x7F) ;
74 outppw (addrLo, regs[1] & 0xFFFF) ;
75 xlogDesc.cnt = inppw(ioaddr) ;
76 outpp (addrHi, (regs[2] >> 16) & 0x7F) ;
77 outppw (addrLo, regs[2] & 0xFFFF) ;
78 xlogDesc.out = inppw(ioaddr) ;
79 xlogDesc.buf = Xlog ;
80 regs[0] &= IoAdapter->MemorySize - 1 ;
81 if ( (regs[0] < IoAdapter->MemorySize - 1) )
82 {
83 size = IoAdapter->MemorySize - regs[0] ;
84 if ( size > MAX_XLOG_SIZE )
85 size = MAX_XLOG_SIZE ;
86 for ( i = 0 ; i < (size / sizeof(*Xlog)) ; regs[0] += 2 )
87 {
88 outpp (addrHi, (regs[0] >> 16) & 0x7F) ;
89 outppw (addrLo, regs[0] & 0xFFFF) ;
90 Xlog[i++] = inppw(ioaddr) ;
91 }
92 dump_xlog_buffer (IoAdapter, &xlogDesc) ;
93 diva_os_free (0, Xlog) ;
94 IoAdapter->trapped = 2 ;
95 }
96 outpp (addrHi, (byte)((BRI_UNCACHED_ADDR (IoAdapter->MemoryBase + IoAdapter->MemorySize -
97 BRI_SHARED_RAM_SIZE)) >> 16)) ;
98 outppw (addrLo, 0x00) ;
99 DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port);
100}
101/* ---------------------------------------------------------------------
102 Reset hardware
103 --------------------------------------------------------------------- */
104static void reset_bri_hardware (PISDN_ADAPTER IoAdapter) {
105 byte __iomem *p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
106 outpp (p, 0x00) ;
107 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
108}
109/* ---------------------------------------------------------------------
110 Halt system
111 --------------------------------------------------------------------- */
112static void stop_bri_hardware (PISDN_ADAPTER IoAdapter) {
113 byte __iomem *p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
114 if (p) {
115 outpp (p, 0x00) ; /* disable interrupts ! */
116 }
117 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
118 p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
119 outpp (p, 0x00) ; /* clear int, halt cpu */
120 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
121}
122static int load_bri_hardware (PISDN_ADAPTER IoAdapter) {
123 return (0);
124}
125/******************************************************************************/
126static int bri_ISR (struct _ISDN_ADAPTER* IoAdapter) {
127 byte __iomem *p;
128
129 p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
130 if ( !(inpp (p) & 0x01) ) {
131 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
132 return (0) ;
133 }
134 /*
135 clear interrupt line
136 */
137 outpp (p, 0x08) ;
138 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
139 IoAdapter->IrqCount++ ;
140 if ( IoAdapter->Initialized ) {
141 diva_os_schedule_soft_isr (&IoAdapter->isr_soft_isr);
142 }
143 return (1) ;
144}
145/* --------------------------------------------------------------------------
146 Disable IRQ in the card hardware
147 -------------------------------------------------------------------------- */
148static void disable_bri_interrupt (PISDN_ADAPTER IoAdapter) {
149 byte __iomem *p;
150 p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
151 if ( p )
152 {
153 outpp (p, 0x00) ; /* disable interrupts ! */
154 }
155 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
156 p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
157 outpp (p, 0x00) ; /* clear int, halt cpu */
158 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
159}
160/* -------------------------------------------------------------------------
161 Fill card entry points
162 ------------------------------------------------------------------------- */
163void prepare_maestra_functions (PISDN_ADAPTER IoAdapter) {
164 ADAPTER *a = &IoAdapter->a ;
165 a->ram_in = io_in ;
166 a->ram_inw = io_inw ;
167 a->ram_in_buffer = io_in_buffer ;
168 a->ram_look_ahead = io_look_ahead ;
169 a->ram_out = io_out ;
170 a->ram_outw = io_outw ;
171 a->ram_out_buffer = io_out_buffer ;
172 a->ram_inc = io_inc ;
173 IoAdapter->MemoryBase = BRI_MEMORY_BASE ;
174 IoAdapter->MemorySize = BRI_MEMORY_SIZE ;
175 IoAdapter->out = pr_out ;
176 IoAdapter->dpc = pr_dpc ;
177 IoAdapter->tst_irq = scom_test_int ;
178 IoAdapter->clr_irq = scom_clear_int ;
179 IoAdapter->pcm = (struct pc_maint *)MIPS_MAINT_OFFS ;
180 IoAdapter->load = load_bri_hardware ;
181 IoAdapter->disIrq = disable_bri_interrupt ;
182 IoAdapter->rstFnc = reset_bri_hardware ;
183 IoAdapter->stop = stop_bri_hardware ;
184 IoAdapter->trapFnc = bri_cpu_trapped ;
185 IoAdapter->diva_isr_handler = bri_ISR;
186 /*
187 Prepare OS dependent functions
188 */
189 diva_os_prepare_maestra_functions (IoAdapter);
190}
191/* -------------------------------------------------------------------------- */
diff --git a/drivers/isdn/hardware/eicon/s_pri.c b/drivers/isdn/hardware/eicon/s_pri.c
new file mode 100644
index 000000000000..18f287888570
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/s_pri.c
@@ -0,0 +1,205 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#include "platform.h"
27#include "di_defs.h"
28#include "pc.h"
29#include "pr_pc.h"
30#include "di.h"
31#include "mi_pc.h"
32#include "pc_maint.h"
33#include "divasync.h"
34#include "io.h"
35#include "helpers.h"
36#include "dsrv_pri.h"
37#include "dsp_defs.h"
38/*****************************************************************************/
39#define MAX_XLOG_SIZE (64 * 1024)
40/* -------------------------------------------------------------------------
41 Does return offset between ADAPTER->ram and real begin of memory
42 ------------------------------------------------------------------------- */
43static dword pri_ram_offset (ADAPTER* a) {
44 return ((dword)MP_SHARED_RAM_OFFSET);
45}
46/* -------------------------------------------------------------------------
47 Recovery XLOG buffer from the card
48 ------------------------------------------------------------------------- */
49static void pri_cpu_trapped (PISDN_ADAPTER IoAdapter) {
50 byte __iomem *base ;
51 word *Xlog ;
52 dword regs[4], TrapID, size ;
53 Xdesc xlogDesc ;
54/*
55 * check for trapped MIPS 46xx CPU, dump exception frame
56 */
57 base = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
58 TrapID = READ_DWORD(&base[0x80]) ;
59 if ( (TrapID == 0x99999999) || (TrapID == 0x99999901) )
60 {
61 dump_trap_frame (IoAdapter, &base[0x90]) ;
62 IoAdapter->trapped = 1 ;
63 }
64 regs[0] = READ_DWORD(&base[MP_PROTOCOL_OFFSET + 0x70]);
65 regs[1] = READ_DWORD(&base[MP_PROTOCOL_OFFSET + 0x74]);
66 regs[2] = READ_DWORD(&base[MP_PROTOCOL_OFFSET + 0x78]);
67 regs[3] = READ_DWORD(&base[MP_PROTOCOL_OFFSET + 0x7c]);
68 regs[0] &= IoAdapter->MemorySize - 1 ;
69 if ( (regs[0] < IoAdapter->MemorySize - 1) )
70 {
71 if ( !(Xlog = (word *)diva_os_malloc (0, MAX_XLOG_SIZE)) ) {
72 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, base);
73 return ;
74 }
75 size = IoAdapter->MemorySize - regs[0] ;
76 if ( size > MAX_XLOG_SIZE )
77 size = MAX_XLOG_SIZE ;
78 memcpy_fromio(Xlog, &base[regs[0]], size) ;
79 xlogDesc.buf = Xlog ;
80 xlogDesc.cnt = READ_WORD(&base[regs[1] & (IoAdapter->MemorySize - 1)]) ;
81 xlogDesc.out = READ_WORD(&base[regs[2] & (IoAdapter->MemorySize - 1)]) ;
82 dump_xlog_buffer (IoAdapter, &xlogDesc) ;
83 diva_os_free (0, Xlog) ;
84 IoAdapter->trapped = 2 ;
85 }
86 DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, base);
87}
88/* -------------------------------------------------------------------------
89 Hardware reset of PRI card
90 ------------------------------------------------------------------------- */
91static void reset_pri_hardware (PISDN_ADAPTER IoAdapter) {
92 byte __iomem *p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
93 WRITE_BYTE(p, _MP_RISC_RESET | _MP_LED1 | _MP_LED2);
94 diva_os_wait (50) ;
95 WRITE_BYTE(p, 0x00);
96 diva_os_wait (50) ;
97 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
98}
99/* -------------------------------------------------------------------------
100 Stop Card Hardware
101 ------------------------------------------------------------------------- */
102static void stop_pri_hardware (PISDN_ADAPTER IoAdapter) {
103 dword i;
104 byte __iomem *p;
105 dword volatile __iomem *cfgReg = (void __iomem *)DIVA_OS_MEM_ATTACH_CFG(IoAdapter);
106 WRITE_DWORD(&cfgReg[3], 0);
107 WRITE_DWORD(&cfgReg[1], 0);
108 DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfgReg);
109 IoAdapter->a.ram_out (&IoAdapter->a, &RAM->SWReg, SWREG_HALT_CPU) ;
110 i = 0 ;
111 while ( (i < 100) && (IoAdapter->a.ram_in (&IoAdapter->a, &RAM->SWReg) != 0) )
112 {
113 diva_os_wait (1) ;
114 i++ ;
115 }
116 DBG_TRC(("%s: PRI stopped (%d)", IoAdapter->Name, i))
117 cfgReg = (void __iomem *)DIVA_OS_MEM_ATTACH_CFG(IoAdapter);
118 WRITE_DWORD(&cfgReg[0],((dword)(~0x03E00000)));
119 DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfgReg);
120 diva_os_wait (1) ;
121 p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
122 WRITE_BYTE(p, _MP_RISC_RESET | _MP_LED1 | _MP_LED2);
123 DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
124}
125static int load_pri_hardware (PISDN_ADAPTER IoAdapter) {
126 return (0);
127}
128/* --------------------------------------------------------------------------
129 PRI Adapter interrupt Service Routine
130 -------------------------------------------------------------------------- */
131static int pri_ISR (struct _ISDN_ADAPTER* IoAdapter) {
132 byte __iomem *cfg = DIVA_OS_MEM_ATTACH_CFG(IoAdapter);
133 if ( !(READ_DWORD(cfg) & 0x80000000) ) {
134 DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfg);
135 return (0) ;
136 }
137 /*
138 clear interrupt line
139 */
140 WRITE_DWORD(cfg, (dword)~0x03E00000) ;
141 DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfg);
142 IoAdapter->IrqCount++ ;
143 if ( IoAdapter->Initialized )
144 {
145 diva_os_schedule_soft_isr (&IoAdapter->isr_soft_isr);
146 }
147 return (1) ;
148}
149/* -------------------------------------------------------------------------
150 Disable interrupt in the card hardware
151 ------------------------------------------------------------------------- */
152static void disable_pri_interrupt (PISDN_ADAPTER IoAdapter) {
153 dword volatile __iomem *cfgReg = (dword volatile __iomem *)DIVA_OS_MEM_ATTACH_CFG(IoAdapter) ;
154 WRITE_DWORD(&cfgReg[3], 0);
155 WRITE_DWORD(&cfgReg[1], 0);
156 WRITE_DWORD(&cfgReg[0], (dword)(~0x03E00000)) ;
157 DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfgReg);
158}
159/* -------------------------------------------------------------------------
160 Install entry points for PRI Adapter
161 ------------------------------------------------------------------------- */
162static void prepare_common_pri_functions (PISDN_ADAPTER IoAdapter) {
163 ADAPTER *a = &IoAdapter->a ;
164 a->ram_in = mem_in ;
165 a->ram_inw = mem_inw ;
166 a->ram_in_buffer = mem_in_buffer ;
167 a->ram_look_ahead = mem_look_ahead ;
168 a->ram_out = mem_out ;
169 a->ram_outw = mem_outw ;
170 a->ram_out_buffer = mem_out_buffer ;
171 a->ram_inc = mem_inc ;
172 a->ram_offset = pri_ram_offset ;
173 a->ram_out_dw = mem_out_dw;
174 a->ram_in_dw = mem_in_dw;
175 a->istream_wakeup = pr_stream;
176 IoAdapter->out = pr_out ;
177 IoAdapter->dpc = pr_dpc ;
178 IoAdapter->tst_irq = scom_test_int ;
179 IoAdapter->clr_irq = scom_clear_int ;
180 IoAdapter->pcm = (struct pc_maint *)(MIPS_MAINT_OFFS
181 - MP_SHARED_RAM_OFFSET) ;
182 IoAdapter->load = load_pri_hardware ;
183 IoAdapter->disIrq = disable_pri_interrupt ;
184 IoAdapter->rstFnc = reset_pri_hardware ;
185 IoAdapter->stop = stop_pri_hardware ;
186 IoAdapter->trapFnc = pri_cpu_trapped ;
187 IoAdapter->diva_isr_handler = pri_ISR;
188}
189/* -------------------------------------------------------------------------
190 Install entry points for PRI Adapter
191 ------------------------------------------------------------------------- */
192void prepare_pri_functions (PISDN_ADAPTER IoAdapter) {
193 IoAdapter->MemorySize = MP_MEMORY_SIZE ;
194 prepare_common_pri_functions (IoAdapter) ;
195 diva_os_prepare_pri_functions (IoAdapter);
196}
197/* -------------------------------------------------------------------------
198 Install entry points for PRI Rev.2 Adapter
199 ------------------------------------------------------------------------- */
200void prepare_pri2_functions (PISDN_ADAPTER IoAdapter) {
201 IoAdapter->MemorySize = MP2_MEMORY_SIZE ;
202 prepare_common_pri_functions (IoAdapter) ;
203 diva_os_prepare_pri2_functions (IoAdapter);
204}
205/* ------------------------------------------------------------------------- */
diff --git a/drivers/isdn/hardware/eicon/sdp_hdr.h b/drivers/isdn/hardware/eicon/sdp_hdr.h
new file mode 100644
index 000000000000..8f61c696b9aa
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/sdp_hdr.h
@@ -0,0 +1,117 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26#ifndef __DIVA_SOFT_DSP_TASK_ENTRY_H__
27#define __DIVA_SOFT_DSP_TASK_ENTRY_H__
28/*
29 The soft DSP image is described by binary header contained on begin of this
30 image:
31OFFSET FROM IMAGE START | VARIABLE
32------------------------------------------------------------------------
33 DIVA_MIPS_TASK_IMAGE_LINK_OFFS | link to the next image
34 ----------------------------------------------------------------------
35 DIVA_MIPS_TASK_IMAGE_GP_OFFS | image gp register value, void*
36 ----------------------------------------------------------------------
37 DIVA_MIPS_TASK_IMAGE_ENTRY_OFFS | diva_mips_sdp_task_entry_t*
38 ----------------------------------------------------------------------
39 DIVA_MIPS_TASK_IMAGE_LOAD_ADDR_OFFS | image image start address (void*)
40 ----------------------------------------------------------------------
41 DIVA_MIPS_TASK_IMAGE_END_ADDR_OFFS | image image end address (void*)
42 ----------------------------------------------------------------------
43 DIVA_MIPS_TASK_IMAGE_ID_STRING_OFFS | image id string char[...];
44 ----------------------------------------------------------------------
45 */
46#define DIVA_MIPS_TASK_IMAGE_LINK_OFFS 0x6C
47#define DIVA_MIPS_TASK_IMAGE_GP_OFFS 0x70
48#define DIVA_MIPS_TASK_IMAGE_ENTRY_OFFS 0x74
49#define DIVA_MIPS_TASK_IMAGE_LOAD_ADDR_OFFS 0x78
50#define DIVA_MIPS_TASK_IMAGE_END_ADDR_OFFS 0x7c
51#define DIVA_MIPS_TASK_IMAGE_ID_STRING_OFFS 0x80
52/*
53 This function is called in order to set GP register of this task
54 This function should be always called before any function of the
55 task is called
56 */
57typedef void (*diva_task_set_prog_gp_proc_t)(void* new_gp);
58/*
59 This function is called to clear .bss at task initialization step
60 */
61typedef void (*diva_task_sys_reset_proc_t)(void);
62/*
63 This function is called in order to provide GP of master call to
64 task, that will be used by calls from the task to the master
65 */
66typedef void (*diva_task_set_main_gp_proc_t)(void* main_gp);
67/*
68 This function is called to provide address of 'dprintf' function
69 to the task
70 */
71typedef word (*diva_prt_proc_t)(char *, ...);
72typedef void (*diva_task_set_prt_proc_t)(diva_prt_proc_t fn);
73/*
74 This function is called to set task PID
75 */
76typedef void (*diva_task_set_pid_proc_t)(dword id);
77/*
78 This function is called for run-time task init
79 */
80typedef int (*diva_task_run_time_init_proc_t)(void*, dword);
81/*
82 This function is called from system scheduler or from timer
83 */
84typedef void (*diva_task_callback_proc_t)(void);
85/*
86 This callback is used by task to get current time im mS
87 */
88typedef dword (*diva_task_get_tick_count_proc_t)(void);
89typedef void (*diva_task_set_get_time_proc_t)(\
90 diva_task_get_tick_count_proc_t fn);
91typedef struct _diva_mips_sdp_task_entry {
92 diva_task_set_prog_gp_proc_t set_gp_proc;
93 diva_task_sys_reset_proc_t sys_reset_proc;
94 diva_task_set_main_gp_proc_t set_main_gp_proc;
95 diva_task_set_prt_proc_t set_dprintf_proc;
96 diva_task_set_pid_proc_t set_pid_proc;
97 diva_task_run_time_init_proc_t run_time_init_proc;
98 diva_task_callback_proc_t task_callback_proc;
99 diva_task_callback_proc_t timer_callback_proc;
100 diva_task_set_get_time_proc_t set_get_time_proc;
101 void* last_entry_proc;
102} diva_mips_sdp_task_entry_t;
103/*
104 'last_entry_proc' should be set to zero and is used for future extensuios
105 */
106typedef struct _diva_mips_sw_task {
107 diva_mips_sdp_task_entry_t sdp_entry;
108 void* sdp_gp_reg;
109 void* own_gp_reg;
110} diva_mips_sw_task_t;
111#if !defined(DIVA_BRI2F_SDP_1_NAME)
112#define DIVA_BRI2F_SDP_1_NAME "sdp0.2q0"
113#endif
114#if !defined(DIVA_BRI2F_SDP_2_NAME)
115#define DIVA_BRI2F_SDP_2_NAME "sdp1.2q0"
116#endif
117#endif
diff --git a/drivers/isdn/hardware/eicon/um_idi.c b/drivers/isdn/hardware/eicon/um_idi.c
new file mode 100644
index 000000000000..6563db998d06
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/um_idi.c
@@ -0,0 +1,885 @@
1/* $Id: um_idi.c,v 1.14 2004/03/21 17:54:37 armin Exp $ */
2
3#include "platform.h"
4#include "di_defs.h"
5#include "pc.h"
6#include "dqueue.h"
7#include "adapter.h"
8#include "entity.h"
9#include "um_xdi.h"
10#include "um_idi.h"
11#include "debuglib.h"
12#include "divasync.h"
13
14#define DIVAS_MAX_XDI_ADAPTERS 64
15
16/* --------------------------------------------------------------------------
17 IMPORTS
18 -------------------------------------------------------------------------- */
19extern void diva_os_wakeup_read(void *os_context);
20extern void diva_os_wakeup_close(void *os_context);
21/* --------------------------------------------------------------------------
22 LOCALS
23 -------------------------------------------------------------------------- */
24static LIST_HEAD(adapter_q);
25static diva_os_spin_lock_t adapter_lock;
26
27static diva_um_idi_adapter_t *diva_um_idi_find_adapter(dword nr);
28static void cleanup_adapter(diva_um_idi_adapter_t * a);
29static void cleanup_entity(divas_um_idi_entity_t * e);
30static int diva_user_mode_idi_adapter_features(diva_um_idi_adapter_t * a,
31 diva_um_idi_adapter_features_t
32 * features);
33static int process_idi_request(divas_um_idi_entity_t * e,
34 const diva_um_idi_req_hdr_t * req);
35static int process_idi_rc(divas_um_idi_entity_t * e, byte rc);
36static int process_idi_ind(divas_um_idi_entity_t * e, byte ind);
37static int write_return_code(divas_um_idi_entity_t * e, byte rc);
38
39/* --------------------------------------------------------------------------
40 MAIN
41 -------------------------------------------------------------------------- */
42int diva_user_mode_idi_init(void)
43{
44 diva_os_initialize_spin_lock(&adapter_lock, "adapter");
45 return (0);
46}
47
48/* --------------------------------------------------------------------------
49 Copy adapter features to user supplied buffer
50 -------------------------------------------------------------------------- */
51static int
52diva_user_mode_idi_adapter_features(diva_um_idi_adapter_t * a,
53 diva_um_idi_adapter_features_t *
54 features)
55{
56 IDI_SYNC_REQ sync_req;
57
58 if ((a) && (a->d.request)) {
59 features->type = a->d.type;
60 features->features = a->d.features;
61 features->channels = a->d.channels;
62 memset(features->name, 0, sizeof(features->name));
63
64 sync_req.GetName.Req = 0;
65 sync_req.GetName.Rc = IDI_SYNC_REQ_GET_NAME;
66 (*(a->d.request)) ((ENTITY *) & sync_req);
67 strlcpy(features->name, sync_req.GetName.name,
68 sizeof(features->name));
69
70 sync_req.GetSerial.Req = 0;
71 sync_req.GetSerial.Rc = IDI_SYNC_REQ_GET_SERIAL;
72 sync_req.GetSerial.serial = 0;
73 (*(a->d.request)) ((ENTITY *) & sync_req);
74 features->serial_number = sync_req.GetSerial.serial;
75 }
76
77 return ((a) ? 0 : -1);
78}
79
80/* --------------------------------------------------------------------------
81 REMOVE ADAPTER
82 -------------------------------------------------------------------------- */
83void diva_user_mode_idi_remove_adapter(int adapter_nr)
84{
85 struct list_head *tmp;
86 diva_um_idi_adapter_t *a;
87
88 list_for_each(tmp, &adapter_q) {
89 a = list_entry(tmp, diva_um_idi_adapter_t, link);
90 if (a->adapter_nr == adapter_nr) {
91 list_del(tmp);
92 cleanup_adapter(a);
93 DBG_LOG(("DIDD: del adapter(%d)", a->adapter_nr));
94 diva_os_free(0, a);
95 break;
96 }
97 }
98}
99
100/* --------------------------------------------------------------------------
101 CALLED ON DRIVER EXIT (UNLOAD)
102 -------------------------------------------------------------------------- */
103void diva_user_mode_idi_finit(void)
104{
105 struct list_head *tmp, *safe;
106 diva_um_idi_adapter_t *a;
107
108 list_for_each_safe(tmp, safe, &adapter_q) {
109 a = list_entry(tmp, diva_um_idi_adapter_t, link);
110 list_del(tmp);
111 cleanup_adapter(a);
112 DBG_LOG(("DIDD: del adapter(%d)", a->adapter_nr));
113 diva_os_free(0, a);
114 }
115 diva_os_destroy_spin_lock(&adapter_lock, "adapter");
116}
117
118/* -------------------------------------------------------------------------
119 CREATE AND INIT IDI ADAPTER
120 ------------------------------------------------------------------------- */
121int diva_user_mode_idi_create_adapter(const DESCRIPTOR * d, int adapter_nr)
122{
123 diva_os_spin_lock_magic_t old_irql;
124 diva_um_idi_adapter_t *a =
125 (diva_um_idi_adapter_t *) diva_os_malloc(0,
126 sizeof
127 (diva_um_idi_adapter_t));
128
129 if (!a) {
130 return (-1);
131 }
132 memset(a, 0x00, sizeof(*a));
133 INIT_LIST_HEAD(&a->entity_q);
134
135 a->d = *d;
136 a->adapter_nr = adapter_nr;
137
138 DBG_LOG(("DIDD_ADD A(%d), type:%02x, features:%04x, channels:%d",
139 adapter_nr, a->d.type, a->d.features, a->d.channels));
140
141 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "create_adapter");
142 list_add_tail(&a->link, &adapter_q);
143 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "create_adapter");
144 return (0);
145}
146
147/* ------------------------------------------------------------------------
148 Find adapter by Adapter number
149 ------------------------------------------------------------------------ */
150static diva_um_idi_adapter_t *diva_um_idi_find_adapter(dword nr)
151{
152 diva_um_idi_adapter_t *a = NULL;
153 struct list_head *tmp;
154
155 list_for_each(tmp, &adapter_q) {
156 a = list_entry(tmp, diva_um_idi_adapter_t, link);
157 DBG_TRC(("find_adapter: (%d)-(%d)", nr, a->adapter_nr));
158 if (a->adapter_nr == (int)nr)
159 break;
160 a = NULL;
161 }
162 return(a);
163}
164
165/* ------------------------------------------------------------------------
166 Cleanup this adapter and cleanup/delete all entities assigned
167 to this adapter
168 ------------------------------------------------------------------------ */
169static void cleanup_adapter(diva_um_idi_adapter_t * a)
170{
171 struct list_head *tmp, *safe;
172 divas_um_idi_entity_t *e;
173
174 list_for_each_safe(tmp, safe, &a->entity_q) {
175 e = list_entry(tmp, divas_um_idi_entity_t, link);
176 list_del(tmp);
177 cleanup_entity(e);
178 if (e->os_context) {
179 diva_os_wakeup_read(e->os_context);
180 diva_os_wakeup_close(e->os_context);
181 }
182 }
183 memset(&a->d, 0x00, sizeof(DESCRIPTOR));
184}
185
186/* ------------------------------------------------------------------------
187 Cleanup, but NOT delete this entity
188 ------------------------------------------------------------------------ */
189static void cleanup_entity(divas_um_idi_entity_t * e)
190{
191 e->os_ref = NULL;
192 e->status = 0;
193 e->adapter = NULL;
194 e->e.Id = 0;
195 e->rc_count = 0;
196
197 e->status |= DIVA_UM_IDI_REMOVED;
198 e->status |= DIVA_UM_IDI_REMOVE_PENDING;
199
200 diva_data_q_finit(&e->data);
201 diva_data_q_finit(&e->rc);
202}
203
204
205/* ------------------------------------------------------------------------
206 Create ENTITY, link it to the adapter and remove pointer to entity
207 ------------------------------------------------------------------------ */
208void *divas_um_idi_create_entity(dword adapter_nr, void *file)
209{
210 divas_um_idi_entity_t *e;
211 diva_um_idi_adapter_t *a;
212 diva_os_spin_lock_magic_t old_irql;
213
214 if ((e = (divas_um_idi_entity_t *) diva_os_malloc(0, sizeof(*e)))) {
215 memset(e, 0x00, sizeof(*e));
216 if (!
217 (e->os_context =
218 diva_os_malloc(0, diva_os_get_context_size()))) {
219 DBG_LOG(("E(%08x) no memory for os context", e));
220 diva_os_free(0, e);
221 return NULL;
222 }
223 memset(e->os_context, 0x00, diva_os_get_context_size());
224
225 if ((diva_data_q_init(&e->data, 2048 + 512, 16))) {
226 diva_os_free(0, e->os_context);
227 diva_os_free(0, e);
228 return NULL;
229 }
230 if ((diva_data_q_init(&e->rc, sizeof(diva_um_idi_ind_hdr_t), 2))) {
231 diva_data_q_finit(&e->data);
232 diva_os_free(0, e->os_context);
233 diva_os_free(0, e);
234 return NULL;
235 }
236
237 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "create_entity");
238 /*
239 Look for Adapter requested
240 */
241 if (!(a = diva_um_idi_find_adapter(adapter_nr))) {
242 /*
243 No adapter was found, or this adapter was removed
244 */
245 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "create_entity");
246
247 DBG_LOG(("A: no adapter(%ld)", adapter_nr));
248
249 cleanup_entity(e);
250 diva_os_free(0, e->os_context);
251 diva_os_free(0, e);
252
253 return NULL;
254 }
255
256 e->os_ref = file; /* link to os handle */
257 e->adapter = a; /* link to adapter */
258
259 list_add_tail(&e->link, &a->entity_q); /* link from adapter */
260
261 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "create_entity");
262
263 DBG_LOG(("A(%ld), create E(%08x)", adapter_nr, e));
264 }
265
266 return (e);
267}
268
269/* ------------------------------------------------------------------------
270 Unlink entity and free memory
271 ------------------------------------------------------------------------ */
272int divas_um_idi_delete_entity(int adapter_nr, void *entity)
273{
274 divas_um_idi_entity_t *e;
275 diva_um_idi_adapter_t *a;
276 diva_os_spin_lock_magic_t old_irql;
277
278 if (!(e = (divas_um_idi_entity_t *) entity))
279 return (-1);
280
281 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "delete_entity");
282 if ((a = e->adapter)) {
283 list_del(&e->link);
284 }
285 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "delete_entity");
286
287 diva_um_idi_stop_wdog(entity);
288 cleanup_entity(e);
289 diva_os_free(0, e->os_context);
290 memset(e, 0x00, sizeof(*e));
291 diva_os_free(0, e);
292
293 DBG_LOG(("A(%d) remove E:%08x", adapter_nr, e));
294
295 return (0);
296}
297
298/* --------------------------------------------------------------------------
299 Called by application to read data from IDI
300 -------------------------------------------------------------------------- */
301int diva_um_idi_read(void *entity,
302 void *os_handle,
303 void *dst,
304 int max_length, divas_um_idi_copy_to_user_fn_t cp_fn)
305{
306 divas_um_idi_entity_t *e;
307 diva_um_idi_adapter_t *a;
308 const void *data;
309 int length, ret = 0;
310 diva_um_idi_data_queue_t *q;
311 diva_os_spin_lock_magic_t old_irql;
312
313 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "read");
314
315 e = (divas_um_idi_entity_t *) entity;
316 if (!e || (!(a = e->adapter)) ||
317 (e->status & DIVA_UM_IDI_REMOVE_PENDING) ||
318 (e->status & DIVA_UM_IDI_REMOVED) ||
319 (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) {
320 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "read");
321 DBG_ERR(("E(%08x) read failed - adapter removed", e))
322 return (-1);
323 }
324
325 DBG_TRC(("A(%d) E(%08x) read(%d)", a->adapter_nr, e, max_length));
326
327 /*
328 Try to read return code first
329 */
330 data = diva_data_q_get_segment4read(&e->rc);
331 q = &e->rc;
332
333 /*
334 No return codes available, read indications now
335 */
336 if (!data) {
337 if (!(e->status & DIVA_UM_IDI_RC_PENDING)) {
338 DBG_TRC(("A(%d) E(%08x) read data", a->adapter_nr, e));
339 data = diva_data_q_get_segment4read(&e->data);
340 q = &e->data;
341 }
342 } else {
343 e->status &= ~DIVA_UM_IDI_RC_PENDING;
344 DBG_TRC(("A(%d) E(%08x) read rc", a->adapter_nr, e));
345 }
346
347 if (data) {
348 if ((length = diva_data_q_get_segment_length(q)) >
349 max_length) {
350 /*
351 Not enough space to read message
352 */
353 DBG_ERR(("A: A(%d) E(%08x) read small buffer",
354 a->adapter_nr, e, ret));
355 diva_os_leave_spin_lock(&adapter_lock, &old_irql,
356 "read");
357 return (-2);
358 }
359 /*
360 Copy it to user, this function does access ONLY locked an verified
361 memory, also we can access it witch spin lock held
362 */
363
364 if ((ret = (*cp_fn) (os_handle, dst, data, length)) >= 0) {
365 /*
366 Acknowledge only if read was successfull
367 */
368 diva_data_q_ack_segment4read(q);
369 }
370 }
371
372
373 DBG_TRC(("A(%d) E(%08x) read=%d", a->adapter_nr, e, ret));
374
375 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "read");
376
377 return (ret);
378}
379
380
381int diva_um_idi_write(void *entity,
382 void *os_handle,
383 const void *src,
384 int length, divas_um_idi_copy_from_user_fn_t cp_fn)
385{
386 divas_um_idi_entity_t *e;
387 diva_um_idi_adapter_t *a;
388 diva_um_idi_req_hdr_t *req;
389 void *data;
390 int ret = 0;
391 diva_os_spin_lock_magic_t old_irql;
392
393 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "write");
394
395 e = (divas_um_idi_entity_t *) entity;
396 if (!e || (!(a = e->adapter)) ||
397 (e->status & DIVA_UM_IDI_REMOVE_PENDING) ||
398 (e->status & DIVA_UM_IDI_REMOVED) ||
399 (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) {
400 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
401 DBG_ERR(("E(%08x) write failed - adapter removed", e))
402 return (-1);
403 }
404
405 DBG_TRC(("A(%d) E(%08x) write(%d)", a->adapter_nr, e, length));
406
407 if ((length < sizeof(*req)) || (length > sizeof(e->buffer))) {
408 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
409 return (-2);
410 }
411
412 if (e->status & DIVA_UM_IDI_RC_PENDING) {
413 DBG_ERR(("A: A(%d) E(%08x) rc pending", a->adapter_nr, e));
414 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
415 return (-1); /* should wait for RC code first */
416 }
417
418 /*
419 Copy function does access only locked verified memory,
420 also it can be called with spin lock held
421 */
422 if ((ret = (*cp_fn) (os_handle, e->buffer, src, length)) < 0) {
423 DBG_TRC(("A: A(%d) E(%08x) write error=%d", a->adapter_nr,
424 e, ret));
425 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
426 return (ret);
427 }
428
429 req = (diva_um_idi_req_hdr_t *) & e->buffer[0];
430
431 switch (req->type) {
432 case DIVA_UM_IDI_GET_FEATURES:{
433 DBG_LOG(("A(%d) get_features", a->adapter_nr));
434 if (!(data =
435 diva_data_q_get_segment4write(&e->data))) {
436 DBG_ERR(("A(%d) get_features, no free buffer",
437 a->adapter_nr));
438 diva_os_leave_spin_lock(&adapter_lock,
439 &old_irql,
440 "write");
441 return (0);
442 }
443 diva_user_mode_idi_adapter_features(a, &(((diva_um_idi_ind_hdr_t
444 *) data)->hdr.features));
445 ((diva_um_idi_ind_hdr_t *) data)->type =
446 DIVA_UM_IDI_IND_FEATURES;
447 ((diva_um_idi_ind_hdr_t *) data)->data_length = 0;
448 diva_data_q_ack_segment4write(&e->data,
449 sizeof(diva_um_idi_ind_hdr_t));
450
451 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
452
453 diva_os_wakeup_read(e->os_context);
454 }
455 break;
456
457 case DIVA_UM_IDI_REQ:
458 case DIVA_UM_IDI_REQ_MAN:
459 case DIVA_UM_IDI_REQ_SIG:
460 case DIVA_UM_IDI_REQ_NET:
461 DBG_TRC(("A(%d) REQ(%02d)-(%02d)-(%08x)", a->adapter_nr,
462 req->Req, req->ReqCh,
463 req->type & DIVA_UM_IDI_REQ_TYPE_MASK));
464 switch (process_idi_request(e, req)) {
465 case -1:
466 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
467 return (-1);
468 case -2:
469 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
470 diva_os_wakeup_read(e->os_context);
471 break;
472 default:
473 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
474 break;
475 }
476 break;
477
478 default:
479 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
480 return (-1);
481 }
482
483 DBG_TRC(("A(%d) E(%08x) write=%d", a->adapter_nr, e, ret));
484
485 return (ret);
486}
487
488/* --------------------------------------------------------------------------
489 CALLBACK FROM XDI
490 -------------------------------------------------------------------------- */
491static void diva_um_idi_xdi_callback(ENTITY * entity)
492{
493 divas_um_idi_entity_t *e = DIVAS_CONTAINING_RECORD(entity,
494 divas_um_idi_entity_t,
495 e);
496 diva_os_spin_lock_magic_t old_irql;
497 int call_wakeup = 0;
498
499 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "xdi_callback");
500
501 if (e->e.complete == 255) {
502 if (!(e->status & DIVA_UM_IDI_REMOVE_PENDING)) {
503 diva_um_idi_stop_wdog(e);
504 }
505 if ((call_wakeup = process_idi_rc(e, e->e.Rc))) {
506 if (e->rc_count) {
507 e->rc_count--;
508 }
509 }
510 e->e.Rc = 0;
511 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "xdi_callback");
512
513 if (call_wakeup) {
514 diva_os_wakeup_read(e->os_context);
515 diva_os_wakeup_close(e->os_context);
516 }
517 } else {
518 if (e->status & DIVA_UM_IDI_REMOVE_PENDING) {
519 e->e.RNum = 0;
520 e->e.RNR = 2;
521 } else {
522 call_wakeup = process_idi_ind(e, e->e.Ind);
523 }
524 e->e.Ind = 0;
525 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "xdi_callback");
526 if (call_wakeup) {
527 diva_os_wakeup_read(e->os_context);
528 }
529 }
530}
531
532static int process_idi_request(divas_um_idi_entity_t * e,
533 const diva_um_idi_req_hdr_t * req)
534{
535 int assign = 0;
536 byte Req = (byte) req->Req;
537 dword type = req->type & DIVA_UM_IDI_REQ_TYPE_MASK;
538
539 if (!e->e.Id || !e->e.callback) { /* not assigned */
540 if (Req != ASSIGN) {
541 DBG_ERR(("A: A(%d) E(%08x) not assigned",
542 e->adapter->adapter_nr, e));
543 return (-1); /* NOT ASSIGNED */
544 } else {
545 switch (type) {
546 case DIVA_UM_IDI_REQ_TYPE_MAN:
547 e->e.Id = MAN_ID;
548 DBG_TRC(("A(%d) E(%08x) assign MAN",
549 e->adapter->adapter_nr, e));
550 break;
551
552 case DIVA_UM_IDI_REQ_TYPE_SIG:
553 e->e.Id = DSIG_ID;
554 DBG_TRC(("A(%d) E(%08x) assign SIG",
555 e->adapter->adapter_nr, e));
556 break;
557
558 case DIVA_UM_IDI_REQ_TYPE_NET:
559 e->e.Id = NL_ID;
560 DBG_TRC(("A(%d) E(%08x) assign NET",
561 e->adapter->adapter_nr, e));
562 break;
563
564 default:
565 DBG_ERR(("A: A(%d) E(%08x) unknown type=%08x",
566 e->adapter->adapter_nr, e,
567 type));
568 return (-1);
569 }
570 }
571 e->e.XNum = 1;
572 e->e.RNum = 1;
573 e->e.callback = diva_um_idi_xdi_callback;
574 e->e.X = &e->XData;
575 e->e.R = &e->RData;
576 assign = 1;
577 }
578 e->status |= DIVA_UM_IDI_RC_PENDING;
579 e->e.Req = Req;
580 e->e.ReqCh = (byte) req->ReqCh;
581 e->e.X->PLength = (word) req->data_length;
582 e->e.X->P = (byte *) & req[1]; /* Our buffer is safe */
583
584 DBG_TRC(("A(%d) E(%08x) request(%02x-%02x-%02x (%d))",
585 e->adapter->adapter_nr, e, e->e.Id, e->e.Req,
586 e->e.ReqCh, e->e.X->PLength));
587
588 e->rc_count++;
589
590 if (e->adapter && e->adapter->d.request) {
591 diva_um_idi_start_wdog(e);
592 (*(e->adapter->d.request)) (&e->e);
593 }
594
595 if (assign) {
596 if (e->e.Rc == OUT_OF_RESOURCES) {
597 /*
598 XDI has no entities more, call was not forwarded to the card,
599 no callback will be scheduled
600 */
601 DBG_ERR(("A: A(%d) E(%08x) XDI out of entities",
602 e->adapter->adapter_nr, e));
603
604 e->e.Id = 0;
605 e->e.ReqCh = 0;
606 e->e.RcCh = 0;
607 e->e.Ind = 0;
608 e->e.IndCh = 0;
609 e->e.XNum = 0;
610 e->e.RNum = 0;
611 e->e.callback = NULL;
612 e->e.X = NULL;
613 e->e.R = NULL;
614 write_return_code(e, ASSIGN_RC | OUT_OF_RESOURCES);
615 return (-2);
616 } else {
617 e->status |= DIVA_UM_IDI_ASSIGN_PENDING;
618 }
619 }
620
621 return (0);
622}
623
624static int process_idi_rc(divas_um_idi_entity_t * e, byte rc)
625{
626 DBG_TRC(("A(%d) E(%08x) rc(%02x-%02x-%02x)",
627 e->adapter->adapter_nr, e, e->e.Id, rc, e->e.RcCh));
628
629 if (e->status & DIVA_UM_IDI_ASSIGN_PENDING) {
630 e->status &= ~DIVA_UM_IDI_ASSIGN_PENDING;
631 if (rc != ASSIGN_OK) {
632 DBG_ERR(("A: A(%d) E(%08x) ASSIGN failed",
633 e->adapter->adapter_nr, e));
634 e->e.callback = NULL;
635 e->e.Id = 0;
636 e->e.Req = 0;
637 e->e.ReqCh = 0;
638 e->e.Rc = 0;
639 e->e.RcCh = 0;
640 e->e.Ind = 0;
641 e->e.IndCh = 0;
642 e->e.X = NULL;
643 e->e.R = NULL;
644 e->e.XNum = 0;
645 e->e.RNum = 0;
646 }
647 }
648 if ((e->e.Req == REMOVE) && e->e.Id && (rc == 0xff)) {
649 DBG_ERR(("A: A(%d) E(%08x) discard OK in REMOVE",
650 e->adapter->adapter_nr, e));
651 return (0); /* let us do it in the driver */
652 }
653 if ((e->e.Req == REMOVE) && (!e->e.Id)) { /* REMOVE COMPLETE */
654 e->e.callback = NULL;
655 e->e.Id = 0;
656 e->e.Req = 0;
657 e->e.ReqCh = 0;
658 e->e.Rc = 0;
659 e->e.RcCh = 0;
660 e->e.Ind = 0;
661 e->e.IndCh = 0;
662 e->e.X = NULL;
663 e->e.R = NULL;
664 e->e.XNum = 0;
665 e->e.RNum = 0;
666 e->rc_count = 0;
667 }
668 if ((e->e.Req == REMOVE) && (rc != 0xff)) { /* REMOVE FAILED */
669 DBG_ERR(("A: A(%d) E(%08x) REMOVE FAILED",
670 e->adapter->adapter_nr, e));
671 }
672 write_return_code(e, rc);
673
674 return (1);
675}
676
677static int process_idi_ind(divas_um_idi_entity_t * e, byte ind)
678{
679 int do_wakeup = 0;
680
681 if (e->e.complete != 0x02) {
682 diva_um_idi_ind_hdr_t *pind =
683 (diva_um_idi_ind_hdr_t *)
684 diva_data_q_get_segment4write(&e->data);
685 if (pind) {
686 e->e.RNum = 1;
687 e->e.R->P = (byte *) & pind[1];
688 e->e.R->PLength =
689 (word) (diva_data_q_get_max_length(&e->data) -
690 sizeof(*pind));
691 DBG_TRC(("A(%d) E(%08x) ind_1(%02x-%02x-%02x)-[%d-%d]",
692 e->adapter->adapter_nr, e, e->e.Id, ind,
693 e->e.IndCh, e->e.RLength,
694 e->e.R->PLength));
695
696 } else {
697 DBG_TRC(("A(%d) E(%08x) ind(%02x-%02x-%02x)-RNR",
698 e->adapter->adapter_nr, e, e->e.Id, ind,
699 e->e.IndCh));
700 e->e.RNum = 0;
701 e->e.RNR = 1;
702 do_wakeup = 1;
703 }
704 } else {
705 diva_um_idi_ind_hdr_t *pind =
706 (diva_um_idi_ind_hdr_t *) (e->e.R->P);
707
708 DBG_TRC(("A(%d) E(%08x) ind(%02x-%02x-%02x)-[%d]",
709 e->adapter->adapter_nr, e, e->e.Id, ind,
710 e->e.IndCh, e->e.R->PLength));
711
712 pind--;
713 pind->type = DIVA_UM_IDI_IND;
714 pind->hdr.ind.Ind = ind;
715 pind->hdr.ind.IndCh = e->e.IndCh;
716 pind->data_length = e->e.R->PLength;
717 diva_data_q_ack_segment4write(&e->data,
718 (int) (sizeof(*pind) +
719 e->e.R->PLength));
720 do_wakeup = 1;
721 }
722
723 if ((e->status & DIVA_UM_IDI_RC_PENDING) && !e->rc.count) {
724 do_wakeup = 0;
725 }
726
727 return (do_wakeup);
728}
729
730/* --------------------------------------------------------------------------
731 Write return code to the return code queue of entity
732 -------------------------------------------------------------------------- */
733static int write_return_code(divas_um_idi_entity_t * e, byte rc)
734{
735 diva_um_idi_ind_hdr_t *prc;
736
737 if (!(prc =
738 (diva_um_idi_ind_hdr_t *) diva_data_q_get_segment4write(&e->rc)))
739 {
740 DBG_ERR(("A: A(%d) E(%08x) rc(%02x) lost",
741 e->adapter->adapter_nr, e, rc));
742 e->status &= ~DIVA_UM_IDI_RC_PENDING;
743 return (-1);
744 }
745
746 prc->type = DIVA_UM_IDI_IND_RC;
747 prc->hdr.rc.Rc = rc;
748 prc->hdr.rc.RcCh = e->e.RcCh;
749 prc->data_length = 0;
750 diva_data_q_ack_segment4write(&e->rc, sizeof(*prc));
751
752 return (0);
753}
754
755/* --------------------------------------------------------------------------
756 Return amount of entries that can be bead from this entity or
757 -1 if adapter was removed
758 -------------------------------------------------------------------------- */
759int diva_user_mode_idi_ind_ready(void *entity, void *os_handle)
760{
761 divas_um_idi_entity_t *e;
762 diva_um_idi_adapter_t *a;
763 diva_os_spin_lock_magic_t old_irql;
764 int ret;
765
766 if (!entity)
767 return (-1);
768 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "ind_ready");
769 e = (divas_um_idi_entity_t *) entity;
770 a = e->adapter;
771
772 if ((!a) || (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) {
773 /*
774 Adapter was unloaded
775 */
776 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "ind_ready");
777 return (-1); /* adapter was removed */
778 }
779 if (e->status & DIVA_UM_IDI_REMOVED) {
780 /*
781 entity was removed as result of adapter removal
782 user should assign this entity again
783 */
784 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "ind_ready");
785 return (-1);
786 }
787
788 ret = e->rc.count + e->data.count;
789
790 if ((e->status & DIVA_UM_IDI_RC_PENDING) && !e->rc.count) {
791 ret = 0;
792 }
793
794 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "ind_ready");
795
796 return (ret);
797}
798
799void *diva_um_id_get_os_context(void *entity)
800{
801 return (((divas_um_idi_entity_t *) entity)->os_context);
802}
803
804int divas_um_idi_entity_assigned(void *entity)
805{
806 divas_um_idi_entity_t *e;
807 diva_um_idi_adapter_t *a;
808 int ret;
809 diva_os_spin_lock_magic_t old_irql;
810
811 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "assigned?");
812
813
814 e = (divas_um_idi_entity_t *) entity;
815 if (!e || (!(a = e->adapter)) ||
816 (e->status & DIVA_UM_IDI_REMOVED) ||
817 (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) {
818 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "assigned?");
819 return (0);
820 }
821
822 e->status |= DIVA_UM_IDI_REMOVE_PENDING;
823
824 ret = (e->e.Id || e->rc_count
825 || (e->status & DIVA_UM_IDI_ASSIGN_PENDING));
826
827 DBG_TRC(("Id:%02x, rc_count:%d, status:%08x", e->e.Id, e->rc_count,
828 e->status))
829
830 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "assigned?");
831
832 return (ret);
833}
834
835int divas_um_idi_entity_start_remove(void *entity)
836{
837 divas_um_idi_entity_t *e;
838 diva_um_idi_adapter_t *a;
839 diva_os_spin_lock_magic_t old_irql;
840
841 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "start_remove");
842
843 e = (divas_um_idi_entity_t *) entity;
844 if (!e || (!(a = e->adapter)) ||
845 (e->status & DIVA_UM_IDI_REMOVED) ||
846 (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) {
847 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove");
848 return (0);
849 }
850
851 if (e->rc_count) {
852 /*
853 Entity BUSY
854 */
855 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove");
856 return (1);
857 }
858
859 if (!e->e.Id) {
860 /*
861 Remove request was already pending, and arrived now
862 */
863 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove");
864 return (0); /* REMOVE was pending */
865 }
866
867 /*
868 Now send remove request
869 */
870 e->e.Req = REMOVE;
871 e->e.ReqCh = 0;
872
873 e->rc_count++;
874
875 DBG_TRC(("A(%d) E(%08x) request(%02x-%02x-%02x (%d))",
876 e->adapter->adapter_nr, e, e->e.Id, e->e.Req,
877 e->e.ReqCh, e->e.X->PLength));
878
879 if (a->d.request)
880 (*(a->d.request)) (&e->e);
881
882 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove");
883
884 return (0);
885}
diff --git a/drivers/isdn/hardware/eicon/um_idi.h b/drivers/isdn/hardware/eicon/um_idi.h
new file mode 100644
index 000000000000..141072f8881e
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/um_idi.h
@@ -0,0 +1,43 @@
1/* $Id: um_idi.h,v 1.6 2004/03/21 17:26:01 armin Exp $ */
2
3#ifndef __DIVA_USER_MODE_IDI_CORE_H__
4#define __DIVA_USER_MODE_IDI_CORE_H__
5
6
7/*
8 interface between UM IDI core and OS dependent part
9 */
10int diva_user_mode_idi_init(void);
11void diva_user_mode_idi_finit(void);
12void *divas_um_idi_create_entity(dword adapter_nr, void *file);
13int divas_um_idi_delete_entity(int adapter_nr, void *entity);
14
15typedef int (*divas_um_idi_copy_to_user_fn_t) (void *os_handle,
16 void *dst,
17 const void *src,
18 int length);
19typedef int (*divas_um_idi_copy_from_user_fn_t) (void *os_handle,
20 void *dst,
21 const void *src,
22 int length);
23
24int diva_um_idi_read(void *entity,
25 void *os_handle,
26 void *dst,
27 int max_length, divas_um_idi_copy_to_user_fn_t cp_fn);
28
29int diva_um_idi_write(void *entity,
30 void *os_handle,
31 const void *src,
32 int length, divas_um_idi_copy_from_user_fn_t cp_fn);
33
34int diva_user_mode_idi_ind_ready(void *entity, void *os_handle);
35void *diva_um_id_get_os_context(void *entity);
36int diva_os_get_context_size(void);
37int divas_um_idi_entity_assigned(void *entity);
38int divas_um_idi_entity_start_remove(void *entity);
39
40void diva_um_idi_start_wdog(void *entity);
41void diva_um_idi_stop_wdog(void *entity);
42
43#endif
diff --git a/drivers/isdn/hardware/eicon/um_xdi.h b/drivers/isdn/hardware/eicon/um_xdi.h
new file mode 100644
index 000000000000..b48fc042a5bc
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/um_xdi.h
@@ -0,0 +1,68 @@
1/* $Id: um_xdi.h,v 1.1.2.2 2002/10/02 14:38:38 armin Exp $ */
2
3#ifndef __DIVA_USER_MODE_XDI_H__
4#define __DIVA_USER_MODE_XDI_H__
5
6/*
7 Contains declaratiom of structures shared between application
8 and user mode idi driver
9*/
10
11typedef struct _diva_um_idi_adapter_features {
12 dword type;
13 dword features;
14 dword channels;
15 dword serial_number;
16 char name[128];
17} diva_um_idi_adapter_features_t;
18
19#define DIVA_UM_IDI_REQ_MASK 0x0000FFFF
20#define DIVA_UM_IDI_REQ_TYPE_MASK (~(DIVA_UM_IDI_REQ_MASK))
21#define DIVA_UM_IDI_GET_FEATURES 1 /* trigger features indication */
22#define DIVA_UM_IDI_REQ 2
23#define DIVA_UM_IDI_REQ_TYPE_MAN 0x10000000
24#define DIVA_UM_IDI_REQ_TYPE_SIG 0x20000000
25#define DIVA_UM_IDI_REQ_TYPE_NET 0x30000000
26#define DIVA_UM_IDI_REQ_MAN (DIVA_UM_IDI_REQ | DIVA_UM_IDI_REQ_TYPE_MAN)
27#define DIVA_UM_IDI_REQ_SIG (DIVA_UM_IDI_REQ | DIVA_UM_IDI_REQ_TYPE_SIG)
28#define DIVA_UM_IDI_REQ_NET (DIVA_UM_IDI_REQ | DIVA_UM_IDI_REQ_TYPE_NET)
29/*
30 data_length bytes will follow this structure
31*/
32typedef struct _diva_um_idi_req_hdr {
33 dword type;
34 dword Req;
35 dword ReqCh;
36 dword data_length;
37} diva_um_idi_req_hdr_t;
38
39typedef struct _diva_um_idi_ind_parameters {
40 dword Ind;
41 dword IndCh;
42} diva_um_idi_ind_parameters_t;
43
44typedef struct _diva_um_idi_rc_parameters {
45 dword Rc;
46 dword RcCh;
47} diva_um_idi_rc_parameters_t;
48
49typedef union _diva_um_idi_ind {
50 diva_um_idi_adapter_features_t features;
51 diva_um_idi_ind_parameters_t ind;
52 diva_um_idi_rc_parameters_t rc;
53} diva_um_idi_ind_t;
54
55#define DIVA_UM_IDI_IND_FEATURES 1 /* features indication */
56#define DIVA_UM_IDI_IND 2
57#define DIVA_UM_IDI_IND_RC 3
58/*
59 data_length bytes of data follow
60 this structure
61*/
62typedef struct _diva_um_idi_ind_hdr {
63 dword type;
64 diva_um_idi_ind_t hdr;
65 dword data_length;
66} diva_um_idi_ind_hdr_t;
67
68#endif
diff --git a/drivers/isdn/hardware/eicon/xdi_adapter.h b/drivers/isdn/hardware/eicon/xdi_adapter.h
new file mode 100644
index 000000000000..a3bd163afb8f
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/xdi_adapter.h
@@ -0,0 +1,70 @@
1/* $Id: xdi_adapter.h,v 1.7 2004/03/21 17:26:01 armin Exp $ */
2
3#ifndef __DIVA_OS_XDI_ADAPTER_H__
4#define __DIVA_OS_XDI_ADAPTER_H__
5
6#define DIVAS_XDI_ADAPTER_BUS_PCI 0
7#define DIVAS_XDI_ADAPTER_BUS_ISA 1
8
9typedef struct _divas_pci_card_resources {
10 byte bus;
11 byte func;
12 void *hdev;
13
14 dword bar[8]; /* contains context of appropriate BAR Register */
15 void __iomem *addr[8]; /* same bar, but mapped into memory */
16 dword length[8]; /* bar length */
17 int mem_type_id[MAX_MEM_TYPE];
18 unsigned int qoffset;
19 byte irq;
20} divas_pci_card_resources_t;
21
22typedef union _divas_card_resources {
23 divas_pci_card_resources_t pci;
24} divas_card_resources_t;
25
26struct _diva_os_xdi_adapter;
27typedef int (*diva_init_card_proc_t) (struct _diva_os_xdi_adapter * a);
28typedef int (*diva_cmd_card_proc_t) (struct _diva_os_xdi_adapter * a,
29 diva_xdi_um_cfg_cmd_t * data,
30 int length);
31typedef void (*diva_xdi_clear_interrupts_proc_t) (struct
32 _diva_os_xdi_adapter *);
33
34#define DIVA_XDI_MBOX_BUSY 1
35#define DIVA_XDI_MBOX_WAIT_XLOG 2
36
37typedef struct _xdi_mbox_t {
38 dword status;
39 diva_xdi_um_cfg_cmd_data_t cmd_data;
40 dword data_length;
41 void *data;
42} xdi_mbox_t;
43
44typedef struct _diva_os_idi_adapter_interface {
45 diva_init_card_proc_t cleanup_adapter_proc;
46 diva_cmd_card_proc_t cmd_proc;
47} diva_os_idi_adapter_interface_t;
48
49typedef struct _diva_os_xdi_adapter {
50 struct list_head link;
51 int CardIndex;
52 int CardOrdinal;
53 int controller; /* number of this controller */
54 int Bus; /* PCI, ISA, ... */
55 divas_card_resources_t resources;
56 char port_name[24];
57 ISDN_ADAPTER xdi_adapter;
58 xdi_mbox_t xdi_mbox;
59 diva_os_idi_adapter_interface_t interface;
60 struct _diva_os_xdi_adapter *slave_adapters[3];
61 void *slave_list;
62 void *proc_adapter_dir; /* adapterX proc entry */
63 void *proc_info; /* info proc entry */
64 void *proc_grp_opt; /* group_optimization */
65 void *proc_d_l1_down; /* dynamic_l1_down */
66 volatile diva_xdi_clear_interrupts_proc_t clear_interrupts_proc;
67 dword dsp_mask;
68} diva_os_xdi_adapter_t;
69
70#endif
diff --git a/drivers/isdn/hardware/eicon/xdi_msg.h b/drivers/isdn/hardware/eicon/xdi_msg.h
new file mode 100644
index 000000000000..3ade28f66698
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/xdi_msg.h
@@ -0,0 +1,127 @@
1/* $Id: xdi_msg.h,v 1.1.2.2 2001/02/16 08:40:36 armin Exp $ */
2
3#ifndef __DIVA_XDI_UM_CFG_MESSSGE_H__
4#define __DIVA_XDI_UM_CFG_MESSAGE_H__
5
6/*
7 Definition of messages used to communicate between
8 XDI device driver and user mode configuration utility
9*/
10
11/*
12 As acknowledge one DWORD - card ordinal will be read from the card
13*/
14#define DIVA_XDI_UM_CMD_GET_CARD_ORDINAL 0
15
16/*
17 no acknowledge will be generated, memory block will be written in the
18 memory at given offset
19*/
20#define DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK 1
21
22/*
23 no acknowledge will be genatated, FPGA will be programmed
24*/
25#define DIVA_XDI_UM_CMD_WRITE_FPGA 2
26
27/*
28 As acknowledge block of SDRAM will be read in the user buffer
29*/
30#define DIVA_XDI_UM_CMD_READ_SDRAM 3
31
32/*
33 As acknowledge dword with serial number will be read in the user buffer
34*/
35#define DIVA_XDI_UM_CMD_GET_SERIAL_NR 4
36
37/*
38 As acknowledge struct consisting from 9 dwords with PCI info.
39 dword[0...7] = 8 PCI BARS
40 dword[9] = IRQ
41*/
42#define DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG 5
43
44/*
45 Reset of the board + activation of primary
46 boot loader
47*/
48#define DIVA_XDI_UM_CMD_RESET_ADAPTER 6
49
50/*
51 Called after code download to start adapter
52 at specified address
53 Start does set new set of features due to fact that we not know
54 if protocol features have changed
55*/
56#define DIVA_XDI_UM_CMD_START_ADAPTER 7
57
58/*
59 Stop adapter, called if user
60 wishes to stop adapter without unload
61 of the driver, to reload adapter with
62 different protocol
63*/
64#define DIVA_XDI_UM_CMD_STOP_ADAPTER 8
65
66/*
67 Get state of current adapter
68 Acknowledge is one dword with following values:
69 0 - adapter ready for download
70 1 - adapter running
71 2 - adapter dead
72 3 - out of service, driver should be restarted or hardware problem
73*/
74#define DIVA_XDI_UM_CMD_GET_CARD_STATE 9
75
76/*
77 Reads XLOG entry from the card
78*/
79#define DIVA_XDI_UM_CMD_READ_XLOG_ENTRY 10
80
81/*
82 Set untranslated protocol code features
83 */
84#define DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES 11
85
86typedef struct _diva_xdi_um_cfg_cmd_data_set_features {
87 dword features;
88} diva_xdi_um_cfg_cmd_data_set_features_t;
89
90typedef struct _diva_xdi_um_cfg_cmd_data_start {
91 dword offset;
92 dword features;
93} diva_xdi_um_cfg_cmd_data_start_t;
94
95typedef struct _diva_xdi_um_cfg_cmd_data_write_sdram {
96 dword ram_number;
97 dword offset;
98 dword length;
99} diva_xdi_um_cfg_cmd_data_write_sdram_t;
100
101typedef struct _diva_xdi_um_cfg_cmd_data_write_fpga {
102 dword fpga_number;
103 dword image_length;
104} diva_xdi_um_cfg_cmd_data_write_fpga_t;
105
106typedef struct _diva_xdi_um_cfg_cmd_data_read_sdram {
107 dword ram_number;
108 dword offset;
109 dword length;
110} diva_xdi_um_cfg_cmd_data_read_sdram_t;
111
112typedef union _diva_xdi_um_cfg_cmd_data {
113 diva_xdi_um_cfg_cmd_data_write_sdram_t write_sdram;
114 diva_xdi_um_cfg_cmd_data_write_fpga_t write_fpga;
115 diva_xdi_um_cfg_cmd_data_read_sdram_t read_sdram;
116 diva_xdi_um_cfg_cmd_data_start_t start;
117 diva_xdi_um_cfg_cmd_data_set_features_t features;
118} diva_xdi_um_cfg_cmd_data_t;
119
120typedef struct _diva_xdi_um_cfg_cmd {
121 dword adapter; /* Adapter number 1...N */
122 dword command;
123 diva_xdi_um_cfg_cmd_data_t command_data;
124 dword data_length; /* Plain binary data will follow */
125} diva_xdi_um_cfg_cmd_t;
126
127#endif
diff --git a/drivers/isdn/hardware/eicon/xdi_vers.h b/drivers/isdn/hardware/eicon/xdi_vers.h
new file mode 100644
index 000000000000..cf3494185b9d
--- /dev/null
+++ b/drivers/isdn/hardware/eicon/xdi_vers.h
@@ -0,0 +1,26 @@
1
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26static char diva_xdi_common_code_build[] = "102-52";