diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /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')
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 | # | ||
4 | comment "CAPI hardware drivers" | ||
5 | depends on NET && ISDN && ISDN_CAPI | ||
6 | |||
7 | source "drivers/isdn/hardware/avm/Kconfig" | ||
8 | |||
9 | source "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 | |||
5 | obj-$(CONFIG_CAPI_AVM) += avm/ | ||
6 | obj-$(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 | |||
5 | menu "Active AVM cards" | ||
6 | depends on NET && ISDN && ISDN_CAPI!=n | ||
7 | |||
8 | config CAPI_AVM | ||
9 | bool "Support AVM cards" | ||
10 | help | ||
11 | Enable support for AVM active ISDN cards. | ||
12 | |||
13 | config 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 | |||
19 | config 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 | |||
25 | config 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 | |||
31 | config 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 | |||
38 | config 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 | |||
44 | config 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 | |||
51 | config 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 | |||
58 | config 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 | |||
65 | endmenu | ||
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 | |||
5 | obj-$(CONFIG_ISDN_DRV_AVMB1_B1ISA) += b1isa.o b1.o | ||
6 | obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCI) += b1pci.o b1.o b1dma.o | ||
7 | obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCMCIA) += b1pcmcia.o b1.o | ||
8 | obj-$(CONFIG_ISDN_DRV_AVMB1_AVM_CS) += avm_cs.o | ||
9 | obj-$(CONFIG_ISDN_DRV_AVMB1_T1ISA) += t1isa.o b1.o | ||
10 | obj-$(CONFIG_ISDN_DRV_AVMB1_T1PCI) += t1pci.o b1.o b1dma.o | ||
11 | obj-$(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 | |||
40 | MODULE_DESCRIPTION("CAPI4Linux: PCMCIA client driver for AVM B1/M1/M2"); | ||
41 | MODULE_AUTHOR("Carsten Paeth"); | ||
42 | MODULE_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 | |||
55 | static void avmcs_config(dev_link_t *link); | ||
56 | static void avmcs_release(dev_link_t *link); | ||
57 | static 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 | |||
66 | static dev_link_t *avmcs_attach(void); | ||
67 | static 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 | |||
75 | static 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 | |||
87 | static 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 | |||
106 | typedef 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 | |||
122 | static 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 | |||
194 | static 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 | |||
236 | static 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 | |||
244 | static 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 | |||
252 | static 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 | |||
260 | static 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 | |||
338 | found_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 | |||
424 | static 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 | |||
456 | static 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 | |||
489 | static 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 | |||
498 | static int __init avmcs_init(void) | ||
499 | { | ||
500 | return pcmcia_register_driver(&avmcs_driver); | ||
501 | } | ||
502 | |||
503 | static void __exit avmcs_exit(void) | ||
504 | { | ||
505 | pcmcia_unregister_driver(&avmcs_driver); | ||
506 | BUG_ON(dev_list != NULL); | ||
507 | } | ||
508 | |||
509 | module_init(avmcs_init); | ||
510 | module_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 | |||
34 | enum 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 | |||
46 | typedef struct avmcard_dmabuf { | ||
47 | long size; | ||
48 | u8 *dmabuf; | ||
49 | dma_addr_t dmaaddr; | ||
50 | } avmcard_dmabuf; | ||
51 | |||
52 | typedef 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 | |||
62 | typedef 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 | |||
77 | typedef 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 | |||
103 | extern 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 | |||
219 | static 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 | |||
228 | static inline int b1_rx_full(unsigned int base) | ||
229 | { | ||
230 | return inb(base + B1_INSTAT) & 0x1; | ||
231 | } | ||
232 | |||
233 | static 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 | |||
243 | static 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 | |||
253 | static inline int b1_tx_empty(unsigned int base) | ||
254 | { | ||
255 | return inb(base + B1_OUTSTAT) & 0x1; | ||
256 | } | ||
257 | |||
258 | static 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 | |||
264 | static 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 | |||
273 | static 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 | |||
281 | static 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 | |||
291 | static 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 | |||
300 | static 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 | |||
309 | static 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 | |||
318 | static 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 | |||
330 | static inline unsigned char b1_disable_irq(unsigned int base) | ||
331 | { | ||
332 | return b1outp(base, B1_INSTAT, 0x00); | ||
333 | } | ||
334 | |||
335 | /* ---------------------------------------------------------------- */ | ||
336 | |||
337 | static 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 | |||
344 | static 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 | |||
386 | static inline void t1outp(unsigned int base, | ||
387 | unsigned short offset, | ||
388 | unsigned char value) | ||
389 | { | ||
390 | outb(value, base + offset); | ||
391 | } | ||
392 | |||
393 | static inline unsigned char t1inp(unsigned int base, | ||
394 | unsigned short offset) | ||
395 | { | ||
396 | return inb(base + offset); | ||
397 | } | ||
398 | |||
399 | static inline int t1_isfastlink(unsigned int base) | ||
400 | { | ||
401 | return (inb(base + T1_IDENT) & ~0x82) == 1; | ||
402 | } | ||
403 | |||
404 | static inline unsigned char t1_fifostatus(unsigned int base) | ||
405 | { | ||
406 | return inb(base + T1_FIFOSTAT); | ||
407 | } | ||
408 | |||
409 | static 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 | |||
464 | static 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 | |||
497 | static inline void t1_disable_irq(unsigned int base) | ||
498 | { | ||
499 | t1outp(base, T1_IRQMASTER, 0x00); | ||
500 | } | ||
501 | |||
502 | static 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 | |||
514 | static 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 */ | ||
544 | avmcard *b1_alloc_card(int nr_controllers); | ||
545 | void b1_free_card(avmcard *card); | ||
546 | int b1_detect(unsigned int base, enum avmcardtype cardtype); | ||
547 | void b1_getrevision(avmcard *card); | ||
548 | int b1_load_t4file(avmcard *card, capiloaddatapart * t4file); | ||
549 | int b1_load_config(avmcard *card, capiloaddatapart * config); | ||
550 | int b1_loaded(avmcard *card); | ||
551 | |||
552 | int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data); | ||
553 | void b1_reset_ctr(struct capi_ctr *ctrl); | ||
554 | void b1_register_appl(struct capi_ctr *ctrl, u16 appl, | ||
555 | capi_register_params *rp); | ||
556 | void b1_release_appl(struct capi_ctr *ctrl, u16 appl); | ||
557 | u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); | ||
558 | void b1_parse_version(avmctrl_info *card); | ||
559 | irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs); | ||
560 | |||
561 | int b1ctl_read_proc(char *page, char **start, off_t off, | ||
562 | int count, int *eof, struct capi_ctr *ctrl); | ||
563 | |||
564 | avmcard_dmainfo *avmcard_dma_alloc(char *name, struct pci_dev *, | ||
565 | long rsize, long ssize); | ||
566 | void avmcard_dma_free(avmcard_dmainfo *); | ||
567 | |||
568 | /* b1dma.c */ | ||
569 | int b1pciv4_detect(avmcard *card); | ||
570 | int t1pci_detect(avmcard *card); | ||
571 | void b1dma_reset(avmcard *card); | ||
572 | irqreturn_t b1dma_interrupt(int interrupt, void *devptr, struct pt_regs *regs); | ||
573 | |||
574 | int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data); | ||
575 | void b1dma_reset_ctr(struct capi_ctr *ctrl); | ||
576 | void b1dma_remove_ctr(struct capi_ctr *ctrl); | ||
577 | void b1dma_register_appl(struct capi_ctr *ctrl, | ||
578 | u16 appl, | ||
579 | capi_register_params *rp); | ||
580 | void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl); | ||
581 | u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); | ||
582 | int 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 | |||
31 | static char *revision = "$Revision: 1.1.2.2 $"; | ||
32 | |||
33 | /* ------------------------------------------------------------- */ | ||
34 | |||
35 | MODULE_DESCRIPTION("CAPI4Linux: Common support for active AVM cards"); | ||
36 | MODULE_AUTHOR("Carsten Paeth"); | ||
37 | MODULE_LICENSE("GPL"); | ||
38 | |||
39 | /* ------------------------------------------------------------- */ | ||
40 | |||
41 | int 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 | |||
62 | avmcard *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 | |||
94 | void b1_free_card(avmcard *card) | ||
95 | { | ||
96 | kfree(card->ctrlinfo); | ||
97 | kfree(card); | ||
98 | } | ||
99 | |||
100 | /* ------------------------------------------------------------- */ | ||
101 | |||
102 | int 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 | |||
145 | void 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 | ||
152 | int 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 | |||
194 | int 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 | |||
245 | int 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 | |||
278 | int 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 | |||
322 | void 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 | |||
336 | void 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 | |||
360 | void 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 | |||
375 | u16 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 | |||
414 | void 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 | |||
488 | irqreturn_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 | /* ------------------------------------------------------------- */ | ||
642 | int 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 | |||
715 | avmcard_dmainfo * | ||
716 | avmcard_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 | |||
757 | void 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 | |||
767 | EXPORT_SYMBOL(avmcard_dma_alloc); | ||
768 | EXPORT_SYMBOL(avmcard_dma_free); | ||
769 | |||
770 | #endif | ||
771 | |||
772 | EXPORT_SYMBOL(b1_irq_table); | ||
773 | |||
774 | EXPORT_SYMBOL(b1_alloc_card); | ||
775 | EXPORT_SYMBOL(b1_free_card); | ||
776 | EXPORT_SYMBOL(b1_detect); | ||
777 | EXPORT_SYMBOL(b1_getrevision); | ||
778 | EXPORT_SYMBOL(b1_load_t4file); | ||
779 | EXPORT_SYMBOL(b1_load_config); | ||
780 | EXPORT_SYMBOL(b1_loaded); | ||
781 | EXPORT_SYMBOL(b1_load_firmware); | ||
782 | EXPORT_SYMBOL(b1_reset_ctr); | ||
783 | EXPORT_SYMBOL(b1_register_appl); | ||
784 | EXPORT_SYMBOL(b1_release_appl); | ||
785 | EXPORT_SYMBOL(b1_send_message); | ||
786 | |||
787 | EXPORT_SYMBOL(b1_parse_version); | ||
788 | EXPORT_SYMBOL(b1_interrupt); | ||
789 | |||
790 | EXPORT_SYMBOL(b1ctl_read_proc); | ||
791 | |||
792 | static 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 | |||
809 | static void __exit b1_exit(void) | ||
810 | { | ||
811 | } | ||
812 | |||
813 | module_init(b1_init); | ||
814 | module_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 | |||
31 | static char *revision = "$Revision: 1.1.2.3 $"; | ||
32 | |||
33 | #undef CONFIG_B1DMA_DEBUG | ||
34 | |||
35 | /* ------------------------------------------------------------- */ | ||
36 | |||
37 | MODULE_DESCRIPTION("CAPI4Linux: DMA support for active AVM cards"); | ||
38 | MODULE_AUTHOR("Carsten Paeth"); | ||
39 | MODULE_LICENSE("GPL"); | ||
40 | |||
41 | static int suppress_pollack = 0; | ||
42 | MODULE_PARM(suppress_pollack, "0-1i"); | ||
43 | |||
44 | /* ------------------------------------------------------------- */ | ||
45 | |||
46 | static 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 | |||
84 | static inline void b1dma_writel(avmcard *card, u32 value, int off) | ||
85 | { | ||
86 | writel(value, card->mbase + off); | ||
87 | } | ||
88 | |||
89 | static inline u32 b1dma_readl(avmcard *card, int off) | ||
90 | { | ||
91 | return readl(card->mbase + off); | ||
92 | } | ||
93 | |||
94 | /* ------------------------------------------------------------- */ | ||
95 | |||
96 | static inline int b1dma_tx_empty(unsigned int port) | ||
97 | { | ||
98 | return inb(port + 0x03) & 0x1; | ||
99 | } | ||
100 | |||
101 | static inline int b1dma_rx_full(unsigned int port) | ||
102 | { | ||
103 | return inb(port + 0x02) & 0x1; | ||
104 | } | ||
105 | |||
106 | static 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 | |||
120 | static 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 | |||
134 | static 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, ®, 4) == 0) { | ||
139 | u32 tmp = val; | ||
140 | return b1dma_tolink(card, &tmp, 4); | ||
141 | } | ||
142 | return -1; | ||
143 | } | ||
144 | |||
145 | static u8 ReadReg(avmcard *card, u32 reg) | ||
146 | { | ||
147 | u8 cmd = 0x01; | ||
148 | if ( b1dma_tolink(card, &cmd, 1) == 0 | ||
149 | && b1dma_tolink(card, ®, 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 | |||
159 | static inline void _put_byte(void **pp, u8 val) | ||
160 | { | ||
161 | u8 *s = *pp; | ||
162 | *s++ = val; | ||
163 | *pp = s; | ||
164 | } | ||
165 | |||
166 | static 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 | |||
176 | static 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 | |||
184 | static 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 | |||
193 | static 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 | |||
205 | static 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 | |||
216 | void 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 | |||
240 | static 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 | |||
289 | int 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 | |||
325 | int 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 | |||
348 | static 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 | |||
366 | static 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 | |||
422 | static 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 | |||
444 | static 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 | |||
577 | static 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 | |||
632 | irqreturn_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 | |||
642 | static 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 | |||
674 | static 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 | |||
697 | int 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 | |||
746 | void 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 | |||
763 | void 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 | |||
800 | void 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 | |||
828 | u16 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 | |||
848 | int 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 | |||
946 | EXPORT_SYMBOL(b1dma_reset); | ||
947 | EXPORT_SYMBOL(t1pci_detect); | ||
948 | EXPORT_SYMBOL(b1pciv4_detect); | ||
949 | EXPORT_SYMBOL(b1dma_interrupt); | ||
950 | |||
951 | EXPORT_SYMBOL(b1dma_load_firmware); | ||
952 | EXPORT_SYMBOL(b1dma_reset_ctr); | ||
953 | EXPORT_SYMBOL(b1dma_register_appl); | ||
954 | EXPORT_SYMBOL(b1dma_release_appl); | ||
955 | EXPORT_SYMBOL(b1dma_send_message); | ||
956 | EXPORT_SYMBOL(b1dmactl_read_proc); | ||
957 | |||
958 | int 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 | |||
975 | void b1dma_exit(void) | ||
976 | { | ||
977 | } | ||
978 | |||
979 | module_init(b1dma_init); | ||
980 | module_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 | |||
30 | static char *revision = "$Revision: 1.1.2.3 $"; | ||
31 | |||
32 | /* ------------------------------------------------------------- */ | ||
33 | |||
34 | MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 ISA card"); | ||
35 | MODULE_AUTHOR("Carsten Paeth"); | ||
36 | MODULE_LICENSE("GPL"); | ||
37 | |||
38 | /* ------------------------------------------------------------- */ | ||
39 | |||
40 | static 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 | |||
61 | static char *b1isa_procinfo(struct capi_ctr *ctrl); | ||
62 | |||
63 | static 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 | |||
149 | static 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 | ||
168 | static struct pci_dev isa_dev[MAX_CARDS]; | ||
169 | static int io[MAX_CARDS]; | ||
170 | static int irq[MAX_CARDS]; | ||
171 | |||
172 | MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i"); | ||
173 | MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i"); | ||
174 | MODULE_PARM_DESC(io, "I/O base address(es)"); | ||
175 | MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); | ||
176 | |||
177 | static 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 | |||
194 | static struct capi_driver capi_driver_b1isa = { | ||
195 | .name = "b1isa", | ||
196 | .revision = "1.0", | ||
197 | .add_card = b1isa_add_card, | ||
198 | }; | ||
199 | |||
200 | static 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 | |||
231 | static 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 | |||
244 | module_init(b1isa_init); | ||
245 | module_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 | |||
31 | static char *revision = "$Revision: 1.1.2.2 $"; | ||
32 | |||
33 | /* ------------------------------------------------------------- */ | ||
34 | |||
35 | static 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 | |||
40 | MODULE_DEVICE_TABLE(pci, b1pci_pci_tbl); | ||
41 | MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 PCI card"); | ||
42 | MODULE_AUTHOR("Carsten Paeth"); | ||
43 | MODULE_LICENSE("GPL"); | ||
44 | |||
45 | /* ------------------------------------------------------------- */ | ||
46 | |||
47 | static 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 | |||
65 | static 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 | |||
147 | static 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 | |||
165 | static 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 | |||
184 | static 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 | |||
286 | static 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 | |||
303 | static 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(¶m, pdev); | ||
326 | #else | ||
327 | retval = b1pci_probe(¶m, 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(¶m, 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 | |||
348 | static 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 | |||
362 | static 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 | |||
369 | static struct capi_driver capi_driver_b1pci = { | ||
370 | .name = "b1pci", | ||
371 | .revision = "1.0", | ||
372 | }; | ||
373 | #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 | ||
374 | static struct capi_driver capi_driver_b1pciv4 = { | ||
375 | .name = "b1pciv4", | ||
376 | .revision = "1.0", | ||
377 | }; | ||
378 | #endif | ||
379 | |||
380 | static 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 | |||
407 | static 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 | |||
416 | module_init(b1pci_init); | ||
417 | module_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 | |||
30 | static char *revision = "$Revision: 1.1.2.2 $"; | ||
31 | |||
32 | /* ------------------------------------------------------------- */ | ||
33 | |||
34 | MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM PCMCIA cards"); | ||
35 | MODULE_AUTHOR("Carsten Paeth"); | ||
36 | MODULE_LICENSE("GPL"); | ||
37 | |||
38 | /* ------------------------------------------------------------- */ | ||
39 | |||
40 | static 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 | |||
56 | static LIST_HEAD(cards); | ||
57 | |||
58 | static char *b1pcmcia_procinfo(struct capi_ctr *ctrl); | ||
59 | |||
60 | static 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 | |||
141 | static 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 | |||
159 | int b1pcmcia_addcard_b1(unsigned int port, unsigned irq) | ||
160 | { | ||
161 | return b1pcmcia_add_card(port, irq, avm_b1pcmcia); | ||
162 | } | ||
163 | |||
164 | int b1pcmcia_addcard_m1(unsigned int port, unsigned irq) | ||
165 | { | ||
166 | return b1pcmcia_add_card(port, irq, avm_m1); | ||
167 | } | ||
168 | |||
169 | int b1pcmcia_addcard_m2(unsigned int port, unsigned irq) | ||
170 | { | ||
171 | return b1pcmcia_add_card(port, irq, avm_m2); | ||
172 | } | ||
173 | |||
174 | int 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 | |||
189 | EXPORT_SYMBOL(b1pcmcia_addcard_b1); | ||
190 | EXPORT_SYMBOL(b1pcmcia_addcard_m1); | ||
191 | EXPORT_SYMBOL(b1pcmcia_addcard_m2); | ||
192 | EXPORT_SYMBOL(b1pcmcia_delcard); | ||
193 | |||
194 | static struct capi_driver capi_driver_b1pcmcia = { | ||
195 | .name = "b1pcmcia", | ||
196 | .revision = "1.0", | ||
197 | }; | ||
198 | |||
199 | static 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 | |||
218 | static void __exit b1pcmcia_exit(void) | ||
219 | { | ||
220 | unregister_capi_driver(&capi_driver_b1pcmcia); | ||
221 | } | ||
222 | |||
223 | module_init(b1pcmcia_init); | ||
224 | module_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 | |||
37 | static char *revision = "$Revision: 1.1.2.2 $"; | ||
38 | |||
39 | /* ------------------------------------------------------------- */ | ||
40 | |||
41 | static int suppress_pollack; | ||
42 | |||
43 | static 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 | |||
49 | MODULE_DEVICE_TABLE(pci, c4_pci_tbl); | ||
50 | MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM C2/C4 cards"); | ||
51 | MODULE_AUTHOR("Carsten Paeth"); | ||
52 | MODULE_LICENSE("GPL"); | ||
53 | MODULE_PARM(suppress_pollack, "0-1i"); | ||
54 | |||
55 | /* ------------------------------------------------------------- */ | ||
56 | |||
57 | static 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 | |||
144 | static 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 | |||
157 | static 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 | |||
175 | static 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 | |||
193 | static 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 | |||
237 | static inline void _put_byte(void **pp, u8 val) | ||
238 | { | ||
239 | u8 *s = *pp; | ||
240 | *s++ = val; | ||
241 | *pp = s; | ||
242 | } | ||
243 | |||
244 | static 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 | |||
254 | static 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 | |||
262 | static 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 | |||
271 | static 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 | |||
283 | static 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 | |||
294 | static 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 | |||
314 | static 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 | |||
408 | static 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 | |||
477 | static 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 | |||
500 | static 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 | |||
663 | static 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 | |||
717 | static 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 | |||
726 | static 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 | |||
750 | static 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 | |||
773 | static 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 | |||
803 | static 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 | |||
844 | static 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 | |||
888 | void 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 | |||
909 | static 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 | |||
936 | void 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 | |||
981 | void 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 | |||
1015 | static 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 | |||
1039 | static 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 | |||
1055 | static 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 | |||
1125 | static 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 | |||
1232 | static 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(¶m, 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 | |||
1261 | static 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 | |||
1268 | static struct capi_driver capi_driver_c2 = { | ||
1269 | .name = "c2", | ||
1270 | .revision = "1.0", | ||
1271 | }; | ||
1272 | |||
1273 | static struct capi_driver capi_driver_c4 = { | ||
1274 | .name = "c4", | ||
1275 | .revision = "1.0", | ||
1276 | }; | ||
1277 | |||
1278 | static 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 | |||
1302 | static 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 | |||
1309 | module_init(c4_init); | ||
1310 | module_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 | |||
32 | static char *revision = "$Revision: 1.1.2.3 $"; | ||
33 | |||
34 | /* ------------------------------------------------------------- */ | ||
35 | |||
36 | MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 HEMA ISA card"); | ||
37 | MODULE_AUTHOR("Carsten Paeth"); | ||
38 | MODULE_LICENSE("GPL"); | ||
39 | |||
40 | /* ------------------------------------------------------------- */ | ||
41 | |||
42 | static 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 | |||
61 | static 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 | |||
134 | static 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 | |||
288 | static 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 | |||
331 | void 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 | |||
346 | static 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 | |||
369 | static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); | ||
370 | static char *t1isa_procinfo(struct capi_ctr *ctrl); | ||
371 | |||
372 | static 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 | |||
458 | static 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 | |||
497 | static 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 | ||
517 | static struct pci_dev isa_dev[MAX_CARDS]; | ||
518 | static int io[MAX_CARDS]; | ||
519 | static int irq[MAX_CARDS]; | ||
520 | static int cardnr[MAX_CARDS]; | ||
521 | |||
522 | MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i"); | ||
523 | MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i"); | ||
524 | MODULE_PARM(cardnr, "1-" __MODULE_STRING(MAX_CARDS) "i"); | ||
525 | MODULE_PARM_DESC(io, "I/O base address(es)"); | ||
526 | MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); | ||
527 | MODULE_PARM_DESC(cardnr, "Card number(s) (as jumpered)"); | ||
528 | |||
529 | static 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 | |||
546 | static struct capi_driver capi_driver_t1isa = { | ||
547 | .name = "t1isa", | ||
548 | .revision = "1.0", | ||
549 | .add_card = t1isa_add_card, | ||
550 | }; | ||
551 | |||
552 | static 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 | |||
583 | static 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 | |||
595 | module_init(t1isa_init); | ||
596 | module_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 | /* ------------------------------------------------------------- */ | ||
33 | static char *revision = "$Revision: 1.1.2.2 $"; | ||
34 | /* ------------------------------------------------------------- */ | ||
35 | |||
36 | static 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 | |||
41 | MODULE_DEVICE_TABLE(pci, t1pci_pci_tbl); | ||
42 | MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 PCI card"); | ||
43 | MODULE_AUTHOR("Carsten Paeth"); | ||
44 | MODULE_LICENSE("GPL"); | ||
45 | |||
46 | /* ------------------------------------------------------------- */ | ||
47 | |||
48 | static char *t1pci_procinfo(struct capi_ctr *ctrl); | ||
49 | |||
50 | static 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 | |||
156 | static 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 | |||
173 | static 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 | |||
191 | static 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(¶m, 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 | |||
219 | static 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 | |||
226 | static struct capi_driver capi_driver_t1pci = { | ||
227 | .name = "t1pci", | ||
228 | .revision = "1.0", | ||
229 | }; | ||
230 | |||
231 | static 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 | |||
253 | static void __exit t1pci_exit(void) | ||
254 | { | ||
255 | unregister_capi_driver(&capi_driver_t1pci); | ||
256 | pci_unregister_driver(&t1pci_pci_driver); | ||
257 | } | ||
258 | |||
259 | module_init(t1pci_init); | ||
260 | module_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 | |||
5 | menu "Active Eicon DIVA Server cards" | ||
6 | depends on NET && ISDN && ISDN_CAPI!=n | ||
7 | |||
8 | config CAPI_EICON | ||
9 | bool "Support Eicon cards" | ||
10 | help | ||
11 | Enable support for Eicon Networks active ISDN cards. | ||
12 | |||
13 | config 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 | |||
21 | config 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 | |||
27 | config 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 | |||
33 | config 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 | |||
40 | config 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 | |||
46 | config ISDN_DIVAS_MAINT | ||
47 | tristate "DIVA Maint driver support" | ||
48 | depends on ISDN_DIVAS && m | ||
49 | help | ||
50 | Enable Divas Maintainance driver. | ||
51 | |||
52 | endmenu | ||
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 | |||
5 | obj-$(CONFIG_ISDN_DIVAS) += divadidd.o divas.o | ||
6 | obj-$(CONFIG_ISDN_DIVAS_MAINT) += diva_mnt.o | ||
7 | obj-$(CONFIG_ISDN_DIVAS_USERIDI) += diva_idi.o | ||
8 | obj-$(CONFIG_ISDN_DIVAS_DIVACAPI) += divacapi.o | ||
9 | |||
10 | # Multipart objects. | ||
11 | |||
12 | divas-y := divasmain.o divasfunc.o di.o io.o istream.o \ | ||
13 | diva.o divasproc.o diva_dma.o | ||
14 | divas-$(CONFIG_ISDN_DIVAS_BRIPCI) += os_bri.o s_bri.o os_4bri.o s_4bri.o | ||
15 | divas-$(CONFIG_ISDN_DIVAS_PRIPCI) += os_pri.o s_pri.o | ||
16 | |||
17 | divacapi-y := capimain.o capifunc.o message.o capidtmf.o | ||
18 | |||
19 | divadidd-y := diva_didd.o diddfunc.o dadapter.o | ||
20 | |||
21 | diva_mnt-y := divamnt.o mntfunc.o debug.o maintidi.o | ||
22 | |||
23 | diva_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 | |||
8 | typedef 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) | ||
51 | struct divas_capi_register_params { | ||
52 | word MessageBufferSize; | ||
53 | word maxLogicalConnection; | ||
54 | word maxBDataBlocks; | ||
55 | word maxBDataLen; | ||
56 | }; | ||
57 | struct divas_capi_version { | ||
58 | word CapiMajor; | ||
59 | word CapiMinor; | ||
60 | word ManuMajor; | ||
61 | word ManuMinor; | ||
62 | }; | ||
63 | typedef 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 */ | ||
119 | typedef struct { | ||
120 | byte structs[1]; /* Additional Info */ | ||
121 | } _ALT_REQP; | ||
122 | /* ALERT-CONFIRM */ | ||
123 | typedef struct { | ||
124 | word Info; | ||
125 | } _ALT_CONP; | ||
126 | /* CONNECT-REQUEST */ | ||
127 | typedef 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 */ | ||
140 | typedef struct { | ||
141 | word Info; | ||
142 | } _CON_CONP; | ||
143 | /* CONNECT-INDICATION */ | ||
144 | typedef 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 */ | ||
156 | typedef 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 */ | ||
164 | typedef struct { | ||
165 | byte structs[1]; /* Connected party number, | ||
166 | Connected party subaddress, | ||
167 | LLC */ | ||
168 | } _CON_A_INDP; | ||
169 | /* CONNECT-ACTIVE-RESPONSE */ | ||
170 | typedef struct { | ||
171 | byte structs[1]; /* empty */ | ||
172 | } _CON_A_RESP; | ||
173 | /* DISCONNECT-REQUEST */ | ||
174 | typedef struct { | ||
175 | byte structs[1]; /* Additional Info */ | ||
176 | } _DIS_REQP; | ||
177 | /* DISCONNECT-CONFIRM */ | ||
178 | typedef struct { | ||
179 | word Info; | ||
180 | } _DIS_CONP; | ||
181 | /* DISCONNECT-INDICATION */ | ||
182 | typedef struct { | ||
183 | word Info; | ||
184 | } _DIS_INDP; | ||
185 | /* DISCONNECT-RESPONSE */ | ||
186 | typedef struct { | ||
187 | byte structs[1]; /* empty */ | ||
188 | } _DIS_RESP; | ||
189 | /* LISTEN-REQUEST */ | ||
190 | typedef 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 */ | ||
197 | typedef struct { | ||
198 | word Info; | ||
199 | } _LIS_CONP; | ||
200 | /* INFO-REQUEST */ | ||
201 | typedef struct { | ||
202 | byte structs[1]; /* Called party number, | ||
203 | Additional Info */ | ||
204 | } _INF_REQP; | ||
205 | /* INFO-CONFIRM */ | ||
206 | typedef struct { | ||
207 | word Info; | ||
208 | } _INF_CONP; | ||
209 | /* INFO-INDICATION */ | ||
210 | typedef struct { | ||
211 | word Number; | ||
212 | byte structs[1]; /* Info element */ | ||
213 | } _INF_INDP; | ||
214 | /* INFO-RESPONSE */ | ||
215 | typedef struct { | ||
216 | byte structs[1]; /* empty */ | ||
217 | } _INF_RESP; | ||
218 | /* SELECT-B-REQUEST */ | ||
219 | typedef struct { | ||
220 | byte structs[1]; /* B-protocol */ | ||
221 | } _SEL_B_REQP; | ||
222 | /* SELECT-B-CONFIRM */ | ||
223 | typedef struct { | ||
224 | word Info; | ||
225 | } _SEL_B_CONP; | ||
226 | /* FACILITY-REQUEST */ | ||
227 | typedef struct { | ||
228 | word Selector; | ||
229 | byte structs[1]; /* Facility parameters */ | ||
230 | } _FAC_REQP; | ||
231 | /* FACILITY-CONFIRM STRUCT FOR SUPPLEMENT. SERVICES */ | ||
232 | typedef struct { | ||
233 | byte struct_length; | ||
234 | word function; | ||
235 | byte length; | ||
236 | word SupplementaryServiceInfo; | ||
237 | dword SupportedServices; | ||
238 | } _FAC_CON_STRUCTS; | ||
239 | /* FACILITY-CONFIRM */ | ||
240 | typedef struct { | ||
241 | word Info; | ||
242 | word Selector; | ||
243 | byte structs[1]; /* Facility parameters */ | ||
244 | } _FAC_CONP; | ||
245 | /* FACILITY-INDICATION */ | ||
246 | typedef struct { | ||
247 | word Selector; | ||
248 | byte structs[1]; /* Facility parameters */ | ||
249 | } _FAC_INDP; | ||
250 | /* FACILITY-RESPONSE */ | ||
251 | typedef struct { | ||
252 | word Selector; | ||
253 | byte structs[1]; /* Facility parameters */ | ||
254 | } _FAC_RESP; | ||
255 | /* CONNECT-B3-REQUEST */ | ||
256 | typedef struct { | ||
257 | byte structs[1]; /* NCPI */ | ||
258 | } _CON_B3_REQP; | ||
259 | /* CONNECT-B3-CONFIRM */ | ||
260 | typedef struct { | ||
261 | word Info; | ||
262 | } _CON_B3_CONP; | ||
263 | /* CONNECT-B3-INDICATION */ | ||
264 | typedef struct { | ||
265 | byte structs[1]; /* NCPI */ | ||
266 | } _CON_B3_INDP; | ||
267 | /* CONNECT-B3-RESPONSE */ | ||
268 | typedef struct { | ||
269 | word Accept; | ||
270 | byte structs[1]; /* NCPI */ | ||
271 | } _CON_B3_RESP; | ||
272 | /* CONNECT-B3-ACTIVE-INDICATION */ | ||
273 | typedef struct { | ||
274 | byte structs[1]; /* NCPI */ | ||
275 | } _CON_B3_A_INDP; | ||
276 | /* CONNECT-B3-ACTIVE-RESPONSE */ | ||
277 | typedef struct { | ||
278 | byte structs[1]; /* empty */ | ||
279 | } _CON_B3_A_RESP; | ||
280 | /* DISCONNECT-B3-REQUEST */ | ||
281 | typedef struct { | ||
282 | byte structs[1]; /* NCPI */ | ||
283 | } _DIS_B3_REQP; | ||
284 | /* DISCONNECT-B3-CONFIRM */ | ||
285 | typedef struct { | ||
286 | word Info; | ||
287 | } _DIS_B3_CONP; | ||
288 | /* DISCONNECT-B3-INDICATION */ | ||
289 | typedef struct { | ||
290 | word Info; | ||
291 | byte structs[1]; /* NCPI */ | ||
292 | } _DIS_B3_INDP; | ||
293 | /* DISCONNECT-B3-RESPONSE */ | ||
294 | typedef struct { | ||
295 | byte structs[1]; /* empty */ | ||
296 | } _DIS_B3_RESP; | ||
297 | /* DATA-B3-REQUEST */ | ||
298 | typedef 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 */ | ||
305 | typedef 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 */ | ||
313 | typedef struct { | ||
314 | word Number; | ||
315 | word Info; | ||
316 | } _DAT_B3_CONP; | ||
317 | /* DATA-B3-INDICATION */ | ||
318 | typedef 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 */ | ||
325 | typedef 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 */ | ||
333 | typedef struct { | ||
334 | word Number; | ||
335 | } _DAT_B3_RESP; | ||
336 | /* RESET-B3-REQUEST */ | ||
337 | typedef struct { | ||
338 | byte structs[1]; /* NCPI */ | ||
339 | } _RES_B3_REQP; | ||
340 | /* RESET-B3-CONFIRM */ | ||
341 | typedef struct { | ||
342 | word Info; | ||
343 | } _RES_B3_CONP; | ||
344 | /* RESET-B3-INDICATION */ | ||
345 | typedef struct { | ||
346 | byte structs[1]; /* NCPI */ | ||
347 | } _RES_B3_INDP; | ||
348 | /* RESET-B3-RESPONSE */ | ||
349 | typedef struct { | ||
350 | byte structs[1]; /* empty */ | ||
351 | } _RES_B3_RESP; | ||
352 | /* CONNECT-B3-T90-ACTIVE-INDICATION */ | ||
353 | typedef struct { | ||
354 | byte structs[1]; /* NCPI */ | ||
355 | } _CON_B3_T90_A_INDP; | ||
356 | /* CONNECT-B3-T90-ACTIVE-RESPONSE */ | ||
357 | typedef struct { | ||
358 | word Reject; | ||
359 | byte structs[1]; /* NCPI */ | ||
360 | } _CON_B3_T90_A_RESP; | ||
361 | /*------------------------------------------------------------------*/ | ||
362 | /* message structure */ | ||
363 | /*------------------------------------------------------------------*/ | ||
364 | typedef struct _API_MSG CAPI_MSG; | ||
365 | typedef struct _MSG_HEADER CAPI_MSG_HEADER; | ||
366 | struct _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 | |||
52 | static 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 | |||
88 | static 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 | |||
127 | static 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 | |||
157 | static 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 | |||
185 | static 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 | |||
249 | static 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 | |||
347 | static 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 | |||
368 | static 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 | |||
389 | static 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 | |||
412 | static 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 | |||
430 | void 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 | |||
449 | void 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 | |||
464 | word 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 | |||
490 | void 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 | |||
678 | void 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 | ||
49 | typedef 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; | ||
65 | typedef struct tag_capidtmf_state | ||
66 | { | ||
67 | byte ulaw; | ||
68 | t_capidtmf_recv_state recv; | ||
69 | } t_capidtmf_state; | ||
70 | word capidtmf_recv_indication (t_capidtmf_state *p_state, byte *buffer); | ||
71 | void capidtmf_recv_block (t_capidtmf_state *p_state, byte *buffer, word length); | ||
72 | void capidtmf_init (t_capidtmf_state *p_state, byte ulaw); | ||
73 | void capidtmf_recv_enable (t_capidtmf_state *p_state, word min_digit_duration, word min_gap_duration); | ||
74 | void 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 | |||
25 | DIVA_CAPI_ADAPTER *adapter = (DIVA_CAPI_ADAPTER *) NULL; | ||
26 | APPL *application = (APPL *) NULL; | ||
27 | byte max_appl = MAX_APPL; | ||
28 | byte max_adapter = 0; | ||
29 | static CAPI_MSG *mapped_msg = (CAPI_MSG *) NULL; | ||
30 | |||
31 | byte UnMapController(byte); | ||
32 | char DRIVERRELEASE_CAPI[32]; | ||
33 | |||
34 | extern void AutomaticLaw(DIVA_CAPI_ADAPTER *); | ||
35 | extern void callback(ENTITY *); | ||
36 | extern word api_remove_start(void); | ||
37 | extern word CapiRelease(word); | ||
38 | extern word CapiRegister(word); | ||
39 | extern word api_put(APPL *, CAPI_MSG *); | ||
40 | |||
41 | static diva_os_spin_lock_t api_lock; | ||
42 | |||
43 | static LIST_HEAD(cards); | ||
44 | |||
45 | static dword notify_handle; | ||
46 | static void DIRequest(ENTITY * e); | ||
47 | static DESCRIPTOR MAdapter; | ||
48 | static DESCRIPTOR DAdapter; | ||
49 | static byte ControllerMap[MAX_DESCRIPTORS + 1]; | ||
50 | |||
51 | |||
52 | static void diva_register_appl(struct capi_ctr *, __u16, | ||
53 | capi_register_params *); | ||
54 | static void diva_release_appl(struct capi_ctr *, __u16); | ||
55 | static char *diva_procinfo(struct capi_ctr *); | ||
56 | static u16 diva_send_message(struct capi_ctr *, | ||
57 | diva_os_message_buffer_s *); | ||
58 | extern void diva_os_set_controller_struct(struct capi_ctr *); | ||
59 | |||
60 | extern void DIVA_DIDD_Read(DESCRIPTOR *, int); | ||
61 | |||
62 | /* | ||
63 | * debug | ||
64 | */ | ||
65 | static void no_printf(unsigned char *, ...); | ||
66 | #include "debuglib.c" | ||
67 | static 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 | */ | ||
88 | static char *diva_procinfo(struct capi_ctr *ctrl) | ||
89 | { | ||
90 | return (ctrl->serial); | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * stop debugging | ||
95 | */ | ||
96 | static 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 | */ | ||
106 | static void no_printf(unsigned char *x, ...) | ||
107 | { | ||
108 | } | ||
109 | |||
110 | /* | ||
111 | * Controller mapping | ||
112 | */ | ||
113 | byte 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 | */ | ||
135 | byte 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 | */ | ||
152 | static 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 | */ | ||
169 | static 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 | */ | ||
188 | void *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 | |||
195 | void *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 | |||
203 | void 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 | |||
209 | void *ReceiveBufferGet(APPL * appl, int Num) | ||
210 | { | ||
211 | return &appl->ReceiveBuffer[Num * appl->MaxDataLength]; | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * api_remove_start/complete for cleanup | ||
216 | */ | ||
217 | void api_remove_complete(void) | ||
218 | { | ||
219 | DBG_PRV1(("api_remove_complete")) | ||
220 | } | ||
221 | |||
222 | /* | ||
223 | * main function called by message.c | ||
224 | */ | ||
225 | void 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 | */ | ||
346 | static 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 | */ | ||
391 | static 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 | */ | ||
450 | static 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 | |||
457 | rescan: | ||
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 | */ | ||
472 | static 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 | */ | ||
486 | static 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 | */ | ||
724 | static 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 | */ | ||
848 | static 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 | */ | ||
878 | static 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 | */ | ||
1010 | static 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 | */ | ||
1025 | static 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 | */ | ||
1051 | static 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 | */ | ||
1099 | static 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 | */ | ||
1115 | int fax_head_line_time(char *buffer) | ||
1116 | { | ||
1117 | return (0); | ||
1118 | } | ||
1119 | |||
1120 | /* | ||
1121 | * init (alloc) main structures | ||
1122 | */ | ||
1123 | static 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 | */ | ||
1151 | static 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 | */ | ||
1164 | static 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 | */ | ||
1184 | int 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 | */ | ||
1212 | void 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 | |||
22 | extern char DRIVERRELEASE_CAPI[]; | ||
23 | |||
24 | typedef 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 | */ | ||
37 | int init_capifunc(void); | ||
38 | void 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 | |||
29 | static char *main_revision = "$Revision: 1.24 $"; | ||
30 | static char *DRIVERNAME = | ||
31 | "Eicon DIVA - CAPI Interface driver (http://www.melware.net)"; | ||
32 | static char *DRIVERLNAME = "divacapi"; | ||
33 | |||
34 | MODULE_DESCRIPTION("CAPI driver for Eicon DIVA cards"); | ||
35 | MODULE_AUTHOR("Cytronics & Melware, Eicon Networks"); | ||
36 | MODULE_SUPPORTED_DEVICE("CAPI and DIVA card drivers"); | ||
37 | MODULE_LICENSE("GPL"); | ||
38 | |||
39 | /* | ||
40 | * get revision number from revision string | ||
41 | */ | ||
42 | static 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 | */ | ||
59 | diva_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 | */ | ||
72 | void 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 | */ | ||
80 | static 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 | */ | ||
102 | void 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 | */ | ||
114 | static 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 | */ | ||
140 | static void DIVA_EXIT_FUNCTION divacapi_exit(void) | ||
141 | { | ||
142 | finit_capifunc(); | ||
143 | printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME); | ||
144 | } | ||
145 | |||
146 | module_init(divacapi_init); | ||
147 | module_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 | */ | ||
247 | typedef 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; | ||
264 | typedef 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_....] ---------------------------------*/ | ||
331 | CARD_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)-*/ | ||
751 | CARD_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*/ | ||
825 | extern CARD_PROPERTIES CardProperties [] ; | ||
826 | extern 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 | ||
903 | typedef struct CARD_FILES_DATA | ||
904 | { | ||
905 | char * Name; | ||
906 | unsigned char Type; | ||
907 | } | ||
908 | CARD_FILES_DATA; | ||
909 | typedef 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 | } | ||
916 | CARD_FILES; | ||
917 | #if CARDTYPE_H_WANT_DATA | ||
918 | #if CARDTYPE_H_WANT_FILE_DATA | ||
919 | CARD_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 | }; | ||
986 | CARD_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*/ | ||
1095 | extern CARD_FILES_DATA CardFData [] ; | ||
1096 | extern 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 | */ | ||
26 | static 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 | -------------------------------------------------------------------------- */ | ||
35 | typedef 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 | ||
41 | static didd_adapter_change_notification_t\ | ||
42 | NotificationTable[DIVA_DIDD_MAX_NOTIFICATIONS]; | ||
43 | /* -------------------------------------------------------------------------- | ||
44 | Array to held adapter information | ||
45 | -------------------------------------------------------------------------- */ | ||
46 | static DESCRIPTOR HandleTable[NEW_MAX_DESCRIPTORS]; | ||
47 | dword Adapters = 0; /* Number of adapters */ | ||
48 | /* -------------------------------------------------------------------------- | ||
49 | Shadow IDI_DIMAINT | ||
50 | and 'shadow' debug stuff | ||
51 | -------------------------------------------------------------------------- */ | ||
52 | static 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 | |||
67 | static 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 | -------------------------------------------------------------------------- */ | ||
76 | static void IDI_CALL_LINK_T diva_dadapter_request (ENTITY IDI_CALL_ENTITY_T *); | ||
77 | static DESCRIPTOR DAdapter = {IDI_DADAPTER, /* Adapter Type */ | ||
78 | 0x00, /* Channels */ | ||
79 | 0x0000, /* Features */ | ||
80 | diva_dadapter_request }; | ||
81 | /* -------------------------------------------------------------------------- | ||
82 | LOCALS | ||
83 | -------------------------------------------------------------------------- */ | ||
84 | static dword diva_register_adapter_callback (\ | ||
85 | didd_adapter_change_callback_t callback, | ||
86 | void IDI_CALL_ENTITY_T* context); | ||
87 | static void diva_remove_adapter_callback (dword handle); | ||
88 | static void diva_notify_adapter_change (DESCRIPTOR* d, int removal); | ||
89 | static diva_os_spin_lock_t didd_spin; | ||
90 | /* -------------------------------------------------------------------------- | ||
91 | Should be called as first step, after driver init | ||
92 | -------------------------------------------------------------------------- */ | ||
93 | void 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 | -------------------------------------------------------------------------- */ | ||
101 | void 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 | -------------------------------------------------------------------------- */ | ||
109 | static 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 | -------------------------------------------------------------------------- */ | ||
146 | static 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 | -------------------------------------------------------------------------- */ | ||
174 | static 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 | -------------------------------------------------------------------------- */ | ||
211 | static 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 | -------------------------------------------------------------------------- */ | ||
269 | static 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 | -------------------------------------------------------------------------- */ | ||
292 | static 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 | -------------------------------------------------------------------------- */ | ||
310 | static 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 | -------------------------------------------------------------------------- */ | ||
362 | void 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 | |||
29 | void diva_didd_load_time_init (void); | ||
30 | void 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 | |||
38 | typedef 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 | |||
72 | typedef 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 | |||
82 | typedef 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 | |||
139 | typedef 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 | |||
15 | static void DI_register (void *arg); | ||
16 | static void DI_deregister (pDbgHandle hDbg); | ||
17 | static void DI_format (int do_lock, word id, int type, char *format, va_list argument_list); | ||
18 | static void DI_format_locked (word id, int type, char *format, va_list argument_list); | ||
19 | static void DI_format_old (word id, char *format, va_list ap) { } | ||
20 | static void DiProcessEventLog (unsigned short id, unsigned long msgID, va_list ap) { } | ||
21 | static void single_p (byte * P, word * PLength, byte Id); | ||
22 | static void diva_maint_xdi_cb (ENTITY* e); | ||
23 | static word SuperTraceCreateReadReq (byte* P, const char* path); | ||
24 | static int diva_mnt_cmp_nmbr (const char* nmbr); | ||
25 | static void diva_free_dma_descriptor (IDI_CALL request, int nr); | ||
26 | static int diva_get_dma_descriptor (IDI_CALL request, dword *dma_magic); | ||
27 | void diva_mnt_internal_dprintf (dword drv_id, dword type, char* p, ...); | ||
28 | |||
29 | static dword MaxDumpSize = 256 ; | ||
30 | static dword MaxXlogSize = 2 + 128 ; | ||
31 | static char TraceFilter[DIVA_MAX_SELECTIVE_FILTER_LENGTH+1]; | ||
32 | static int TraceFilterIdent = -1; | ||
33 | static int TraceFilterChannel = -1; | ||
34 | |||
35 | typedef 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; | ||
53 | static diva_maint_client_t clients[MAX_DESCRIPTORS]; | ||
54 | |||
55 | static void diva_change_management_debug_mask (diva_maint_client_t* pC, dword old_mask); | ||
56 | |||
57 | static 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); | ||
63 | static 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); | ||
68 | static 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 | |||
76 | typedef 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 | |||
86 | typedef 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 | |||
96 | static 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 | |||
104 | static 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 | |||
138 | alloc: | ||
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 | |||
151 | static 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 | |||
169 | static 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 | */ | ||
188 | static MSG_QUEUE* dbg_queue; | ||
189 | static byte* dbg_base; | ||
190 | static int external_dbg_queue; | ||
191 | static diva_os_spin_lock_t dbg_q_lock; | ||
192 | static diva_os_spin_lock_t dbg_adapter_lock; | ||
193 | static int dbg_q_busy; | ||
194 | static volatile dword dbg_sequence; | ||
195 | static dword start_sec; | ||
196 | static 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 | */ | ||
207 | int 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 | */ | ||
273 | void* 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 | */ | ||
303 | dword 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 | */ | ||
312 | diva_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 | */ | ||
335 | void 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 | */ | ||
354 | void 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 | |||
374 | static 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 | |||
485 | static 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 | |||
565 | static 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 | |||
572 | static 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 | */ | ||
733 | int 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 | |||
785 | int 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 | |||
807 | int 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 | |||
841 | static 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 | */ | ||
861 | void 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 | */ | ||
1028 | void 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 | */ | ||
1115 | void* 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 | |||
1127 | int SuperTraceCloseAdapter (void* AdapterHandle) { | ||
1128 | return (0); | ||
1129 | } | ||
1130 | |||
1131 | int 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 | |||
1159 | int 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 | |||
1169 | int 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 | |||
1228 | int 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 | |||
1250 | int 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 | |||
1277 | int 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 | |||
1310 | int 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 | |||
1336 | static 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 | |||
1357 | static void single_p (byte * P, word * PLength, byte Id) { | ||
1358 | P[(*PLength)++] = Id; | ||
1359 | } | ||
1360 | |||
1361 | static 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 | |||
1397 | static 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 | |||
1407 | static 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 | |||
1426 | static 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 | */ | ||
1791 | static 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 | */ | ||
1879 | static 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 | |||
1911 | void 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 | */ | ||
1922 | int 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 | */ | ||
1985 | int 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 | |||
2035 | int 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 | |||
2049 | static 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 | */ | ||
2060 | static 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 | |||
2087 | static 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 | |||
2115 | static 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 | |||
33 | typedef 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 | |||
44 | int diva_maint_init (byte* base, unsigned long length, int do_init); | ||
45 | void* diva_maint_finit (void); | ||
46 | dword diva_dbg_q_length (void); | ||
47 | diva_dbg_entry_head_t* diva_maint_get_message (word* size, | ||
48 | diva_os_spin_lock_magic_t* old_irql); | ||
49 | void diva_maint_ack_message (int do_release, | ||
50 | diva_os_spin_lock_magic_t* old_irql); | ||
51 | void diva_maint_prtComp (char *format, ...); | ||
52 | void diva_maint_wakeup_read (void); | ||
53 | int diva_get_driver_info (dword id, byte* data, int data_length); | ||
54 | int diva_get_driver_dbg_mask (dword id, byte* data); | ||
55 | int diva_set_driver_dbg_mask (dword id, dword mask); | ||
56 | void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d); | ||
57 | void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d); | ||
58 | int diva_mnt_shutdown_xdi_adapters (void); | ||
59 | |||
60 | #define DIVA_MAX_SELECTIVE_FILTER_LENGTH 127 | ||
61 | int diva_set_trace_filter (int filter_length, const char* filter); | ||
62 | int 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 | ||
30 | static DIVA_DI_PRINTF dprintf; | ||
31 | #else /* DIVA_NO_DEBUGLIB */ | ||
32 | |||
33 | _DbgHandle_ myDriverDebugHandle = { 0 /*!Registered*/, DBG_HANDLE_VERSION }; | ||
34 | DIVA_DI_PRINTF dprintf = no_printf; | ||
35 | /*****************************************************************************/ | ||
36 | #define DBG_FUNC(name) \ | ||
37 | void \ | ||
38 | myDbgPrint_##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 | } } | ||
46 | DBG_FUNC(LOG) | ||
47 | DBG_FUNC(FTL) | ||
48 | DBG_FUNC(ERR) | ||
49 | DBG_FUNC(TRC) | ||
50 | DBG_FUNC(MXLOG) | ||
51 | DBG_FUNC(FTL_MXLOG) | ||
52 | void | ||
53 | myDbgPrint_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 | } } | ||
61 | DBG_FUNC(REG) | ||
62 | DBG_FUNC(MEM) | ||
63 | DBG_FUNC(SPL) | ||
64 | DBG_FUNC(IRP) | ||
65 | DBG_FUNC(TIM) | ||
66 | DBG_FUNC(BLK) | ||
67 | DBG_FUNC(TAPI) | ||
68 | DBG_FUNC(NDIS) | ||
69 | DBG_FUNC(CONN) | ||
70 | DBG_FUNC(STAT) | ||
71 | DBG_FUNC(SEND) | ||
72 | DBG_FUNC(RECV) | ||
73 | DBG_FUNC(PRV0) | ||
74 | DBG_FUNC(PRV1) | ||
75 | DBG_FUNC(PRV2) | ||
76 | DBG_FUNC(PRV3) | ||
77 | /*****************************************************************************/ | ||
78 | int | ||
79 | DbgRegister (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 | /*****************************************************************************/ | ||
125 | void | ||
126 | DbgSetLevel (unsigned long dbgMask) | ||
127 | { | ||
128 | myDriverDebugHandle.dbgMask = dbgMask | (DL_EVL | DL_FTL | DL_LOG) ; | ||
129 | } | ||
130 | /*****************************************************************************/ | ||
131 | void | ||
132 | DbgDeregister (void) | ||
133 | { | ||
134 | if ( myDriverDebugHandle.dbg_end ) | ||
135 | { | ||
136 | (myDriverDebugHandle.dbg_end)(&myDriverDebugHandle) ; | ||
137 | } | ||
138 | memset (&myDriverDebugHandle, 0, sizeof(myDriverDebugHandle)) ; | ||
139 | } | ||
140 | void 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 *, ...) ; | ||
136 | DBG_DECL(LOG) | ||
137 | DBG_DECL(FTL) | ||
138 | DBG_DECL(ERR) | ||
139 | DBG_DECL(TRC) | ||
140 | DBG_DECL(MXLOG) | ||
141 | DBG_DECL(FTL_MXLOG) | ||
142 | extern void myDbgPrint_EVL (long, ...) ; | ||
143 | DBG_DECL(REG) | ||
144 | DBG_DECL(MEM) | ||
145 | DBG_DECL(SPL) | ||
146 | DBG_DECL(IRP) | ||
147 | DBG_DECL(TIM) | ||
148 | DBG_DECL(BLK) | ||
149 | DBG_DECL(TAPI) | ||
150 | DBG_DECL(NDIS) | ||
151 | DBG_DECL(CONN) | ||
152 | DBG_DECL(STAT) | ||
153 | DBG_DECL(SEND) | ||
154 | DBG_DECL(RECV) | ||
155 | DBG_DECL(PRV0) | ||
156 | DBG_DECL(PRV1) | ||
157 | DBG_DECL(PRV2) | ||
158 | DBG_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 | ||
221 | extern DIVA_DI_PRINTF dprintf; | ||
222 | extern int DbgRegister (char *drvName, char *drvTag, unsigned long dbgMask) ; | ||
223 | extern void DbgDeregister (void) ; | ||
224 | extern 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 | */ | ||
231 | typedef struct _DbgHandle_ *pDbgHandle ; | ||
232 | typedef void ( * DbgEnd) (pDbgHandle) ; | ||
233 | typedef void ( * DbgLog) (unsigned short, int, char *, va_list) ; | ||
234 | typedef void ( * DbgOld) (unsigned short, char *, va_list) ; | ||
235 | typedef void ( * DbgEv) (unsigned short, unsigned long, va_list) ; | ||
236 | typedef void ( * DbgIrq) (unsigned short, int, char *, va_list) ; | ||
237 | typedef 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_ ; | ||
261 | extern _DbgHandle_ myDriverDebugHandle ; | ||
262 | typedef 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 | ||
299 | typedef 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 | ||
320 | void 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 */ | ||
53 | int 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 | /*------------------------------------------------------------------*/ | ||
43 | void pr_out(ADAPTER * a); | ||
44 | byte pr_dpc(ADAPTER * a); | ||
45 | static byte pr_ready(ADAPTER * a); | ||
46 | static byte isdn_rc(ADAPTER *, byte, byte, byte, word, dword, dword); | ||
47 | static 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)) | ||
59 | static void xdi_xlog (byte *msg, word code, int length); | ||
60 | static byte xdi_xlog_sec = 0; | ||
61 | #else | ||
62 | #define XDI_A_NR(_x_) ((byte)0) | ||
63 | #endif | ||
64 | static void xdi_xlog_rc_event (byte Adapter, | ||
65 | byte Id, byte Ch, byte Rc, byte cb, byte type); | ||
66 | static void xdi_xlog_request (byte Adapter, byte Id, | ||
67 | byte Ch, byte Req, byte type); | ||
68 | static 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 | /*------------------------------------------------------------------*/ | ||
78 | void 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 | } | ||
239 | static 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 | /*------------------------------------------------------------------*/ | ||
255 | byte 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 | } | ||
345 | byte scom_test_int(ADAPTER * a) | ||
346 | { | ||
347 | return a->ram_in(a,(void *)0x3fe); | ||
348 | } | ||
349 | void scom_clear_int(ADAPTER * a) | ||
350 | { | ||
351 | a->ram_out(a,(void *)0x3fe,0); | ||
352 | } | ||
353 | /*------------------------------------------------------------------*/ | ||
354 | /* return code handler */ | ||
355 | /*------------------------------------------------------------------*/ | ||
356 | byte 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 | /*------------------------------------------------------------------*/ | ||
558 | byte 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 | ----------------------------------------------------------- */ | ||
728 | static 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 | ----------------------------------------------------------- */ | ||
757 | static 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 | ------------------------------------------------------------------------ */ | ||
781 | static 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 | ------------------------------------------------------------------------ */ | ||
820 | static 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 */ | ||
40 | typedef struct adapter_s ADAPTER; | ||
41 | struct 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 | /*------------------------------------------------------------------*/ | ||
82 | void pr_out(ADAPTER * a); | ||
83 | byte pr_dpc(ADAPTER * a); | ||
84 | byte scom_test_int(ADAPTER * a); | ||
85 | void scom_clear_int(ADAPTER * a); | ||
86 | /*------------------------------------------------------------------*/ | ||
87 | /* OS specific functions used by IDI common code */ | ||
88 | /*------------------------------------------------------------------*/ | ||
89 | void free_entity(ADAPTER * a, byte e_no); | ||
90 | void assign_queue(ADAPTER * a, byte e_no, word ref); | ||
91 | byte get_assign(ADAPTER * a, word ref); | ||
92 | void req_queue(ADAPTER * a, byte e_no); | ||
93 | byte look_req(ADAPTER * a); | ||
94 | void next_req(ADAPTER * a); | ||
95 | ENTITY * entity_ptr(ADAPTER * a, byte e_no); | ||
96 | #if defined(DIVA_ISTREAM) | ||
97 | struct _diva_xdi_stream_interface; | ||
98 | void diva_xdi_provide_istream_info (ADAPTER* a, | ||
99 | struct _diva_xdi_stream_interface* pI); | ||
100 | void pr_stream (ADAPTER * a); | ||
101 | int diva_istream_write (void* context, | ||
102 | int Id, | ||
103 | void* data, | ||
104 | int length, | ||
105 | int final, | ||
106 | byte usr1, | ||
107 | byte usr2); | ||
108 | int 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 | ||
35 | extern 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 */ | ||
29 | typedef struct get_name_s GET_NAME; | ||
30 | /* The entity_s structure is used to pass all | ||
31 | parameters between application and IDI */ | ||
32 | typedef struct entity_s ENTITY; | ||
33 | typedef struct buffers_s BUFFERS; | ||
34 | typedef struct postcall_s POSTCALL; | ||
35 | typedef 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 | -------------------------------------------------------- */ | ||
43 | typedef void (IDI_CALL_LINK_T * IDI_CALL)(ENTITY IDI_CALL_ENTITY_T *); | ||
44 | typedef struct { | ||
45 | word length; /* length of data/parameter field */ | ||
46 | byte P[270]; /* data/parameter field */ | ||
47 | } DBUFFER; | ||
48 | struct get_name_s { | ||
49 | word command; /* command = 0x0100 */ | ||
50 | byte name[BOARD_NAME_LENGTH]; | ||
51 | }; | ||
52 | struct 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 */ | ||
62 | struct 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 | }; | ||
67 | struct buffers_s { | ||
68 | word PLength; | ||
69 | byte * P; | ||
70 | }; | ||
71 | struct 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 | }; | ||
100 | typedef 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 | -------------------------------------------------------------------------- */ | ||
165 | typedef 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 */ | ||
180 | typedef 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 | */ | ||
26 | static 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 | |||
23 | extern void DIVA_DIDD_Read(void *, int); | ||
24 | extern char *DRIVERRELEASE_DIDD; | ||
25 | static dword notify_handle; | ||
26 | static DESCRIPTOR _DAdapter; | ||
27 | |||
28 | /* | ||
29 | * didd callback function | ||
30 | */ | ||
31 | static 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 | */ | ||
50 | static 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 | */ | ||
82 | static 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 | */ | ||
95 | int 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 | */ | ||
110 | void 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 | |||
29 | PISDN_ADAPTER IoAdapters[MAX_ADAPTER]; | ||
30 | extern IDI_CALL Requests[MAX_ADAPTER]; | ||
31 | extern int create_adapter_proc(diva_os_xdi_adapter_t * a); | ||
32 | extern void remove_adapter_proc(diva_os_xdi_adapter_t * a); | ||
33 | |||
34 | #define DivaIdiReqFunc(N) \ | ||
35 | static void DivaIdiRequest##N(ENTITY *e) \ | ||
36 | { if ( IoAdapters[N] ) (* IoAdapters[N]->DIRequest)(IoAdapters[N], e) ; } | ||
37 | |||
38 | /* | ||
39 | ** Create own 32 Adapters | ||
40 | */ | ||
41 | DivaIdiReqFunc(0) | ||
42 | DivaIdiReqFunc(1) | ||
43 | DivaIdiReqFunc(2) | ||
44 | DivaIdiReqFunc(3) | ||
45 | DivaIdiReqFunc(4) | ||
46 | DivaIdiReqFunc(5) | ||
47 | DivaIdiReqFunc(6) | ||
48 | DivaIdiReqFunc(7) | ||
49 | DivaIdiReqFunc(8) | ||
50 | DivaIdiReqFunc(9) | ||
51 | DivaIdiReqFunc(10) | ||
52 | DivaIdiReqFunc(11) | ||
53 | DivaIdiReqFunc(12) | ||
54 | DivaIdiReqFunc(13) | ||
55 | DivaIdiReqFunc(14) | ||
56 | DivaIdiReqFunc(15) | ||
57 | DivaIdiReqFunc(16) | ||
58 | DivaIdiReqFunc(17) | ||
59 | DivaIdiReqFunc(18) | ||
60 | DivaIdiReqFunc(19) | ||
61 | DivaIdiReqFunc(20) | ||
62 | DivaIdiReqFunc(21) | ||
63 | DivaIdiReqFunc(22) | ||
64 | DivaIdiReqFunc(23) | ||
65 | DivaIdiReqFunc(24) | ||
66 | DivaIdiReqFunc(25) | ||
67 | DivaIdiReqFunc(26) | ||
68 | DivaIdiReqFunc(27) | ||
69 | DivaIdiReqFunc(28) | ||
70 | DivaIdiReqFunc(29) | ||
71 | DivaIdiReqFunc(30) | ||
72 | DivaIdiReqFunc(31) | ||
73 | |||
74 | struct pt_regs; | ||
75 | |||
76 | /* | ||
77 | ** LOCALS | ||
78 | */ | ||
79 | static LIST_HEAD(adapter_queue); | ||
80 | |||
81 | typedef 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 | |||
88 | typedef struct _diva_supported_cards_info { | ||
89 | int CardOrdinal; | ||
90 | diva_init_card_proc_t init_card; | ||
91 | } diva_supported_cards_info_t; | ||
92 | |||
93 | static 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 | |||
137 | static void diva_init_request_array(void); | ||
138 | static void *divas_create_pci_card(int handle, void *pci_dev_handle); | ||
139 | |||
140 | static diva_os_spin_lock_t adapter_lock; | ||
141 | |||
142 | static 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 | |||
155 | static 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 | -------------------------------------------------------------------------- */ | ||
168 | void *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 | -------------------------------------------------------------------------- */ | ||
250 | int 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 | -------------------------------------------------------------------------- */ | ||
262 | static 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 | -------------------------------------------------------------------------- */ | ||
281 | void 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 | -------------------------------------------------------------------------- */ | ||
325 | static 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 | -------------------------------------------------------------------------- */ | ||
371 | void 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 | */ | ||
391 | void *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 | */ | ||
428 | void 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 | |||
439 | int | ||
440 | diva_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 | */ | ||
482 | int | ||
483 | diva_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 | |||
518 | irqreturn_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 | |||
537 | static 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 | |||
573 | void 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 | |||
609 | void 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 | |||
618 | int 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 | |||
658 | void 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 | |||
7 | int divasa_xdi_driver_entry(void); | ||
8 | void divasa_xdi_driver_unload(void); | ||
9 | void *diva_driver_add_card(void *pdev, unsigned long CardOrdinal); | ||
10 | void diva_driver_remove_card(void *pdiva); | ||
11 | |||
12 | typedef int (*divas_xdi_copy_to_user_fn_t) (void *os_handle, void __user *dst, | ||
13 | const void *src, int length); | ||
14 | |||
15 | typedef int (*divas_xdi_copy_from_user_fn_t) (void *os_handle, void *dst, | ||
16 | const void __user *src, int length); | ||
17 | |||
18 | int 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 | |||
21 | int 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 | |||
24 | void *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 | |||
28 | void 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 | |||
26 | static char *main_revision = "$Revision: 1.13.6.4 $"; | ||
27 | |||
28 | static char *DRIVERNAME = | ||
29 | "Eicon DIVA - DIDD table (http://www.melware.net)"; | ||
30 | static char *DRIVERLNAME = "divadidd"; | ||
31 | char *DRIVERRELEASE_DIDD = "2.0"; | ||
32 | |||
33 | static char *main_proc_dir = "eicon"; | ||
34 | |||
35 | MODULE_DESCRIPTION("DIDD table driver for diva drivers"); | ||
36 | MODULE_AUTHOR("Cytronics & Melware, Eicon Networks"); | ||
37 | MODULE_SUPPORTED_DEVICE("Eicon diva drivers"); | ||
38 | MODULE_LICENSE("GPL"); | ||
39 | |||
40 | #define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR) | ||
41 | #define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG) | ||
42 | |||
43 | extern int diddfunc_init(void); | ||
44 | extern void diddfunc_finit(void); | ||
45 | |||
46 | extern void DIVA_DIDD_Read(void *, int); | ||
47 | |||
48 | static struct proc_dir_entry *proc_didd; | ||
49 | struct proc_dir_entry *proc_net_eicon = NULL; | ||
50 | |||
51 | EXPORT_SYMBOL(DIVA_DIDD_Read); | ||
52 | EXPORT_SYMBOL(proc_net_eicon); | ||
53 | |||
54 | static 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 | |||
67 | static int | ||
68 | proc_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 | |||
90 | static 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 | |||
105 | static 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 | |||
111 | static 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 | |||
143 | static 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 | |||
150 | module_init(divadidd_init); | ||
151 | module_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 | */ | ||
32 | struct _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 | */ | ||
41 | struct _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 | */ | ||
50 | void 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 | */ | ||
58 | void 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 | */ | ||
68 | int 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 | */ | ||
81 | void 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 | */ | ||
87 | void 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 | } | ||
92 | void* 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__ | ||
28 | typedef struct _diva_dma_map_entry diva_dma_map_entry_t; | ||
29 | struct _diva_dma_map_entry* diva_alloc_dma_map (void* os_context, int nentries); | ||
30 | void diva_init_dma_map_entry (struct _diva_dma_map_entry* pmap, | ||
31 | int nr, void* virt, dword phys, | ||
32 | void* addr_handle); | ||
33 | int diva_alloc_dma_map_entry (struct _diva_dma_map_entry* pmap); | ||
34 | void diva_free_dma_map_entry (struct _diva_dma_map_entry* pmap, int entry); | ||
35 | void diva_get_dma_map_entry (struct _diva_dma_map_entry* pmap, int nr, | ||
36 | void** pvirt, dword* pphys); | ||
37 | void 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 | */ | ||
42 | void diva_init_dma_map (void* hdev, | ||
43 | struct _diva_dma_map_entry** ppmap, | ||
44 | int nentries); | ||
45 | void diva_free_dma_map (void* hdev, | ||
46 | struct _diva_dma_map_entry* pmap); | ||
47 | void* 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 | |||
6 | void __iomem *divasa_remap_pci_bar(diva_os_xdi_adapter_t *a, | ||
7 | int id, | ||
8 | unsigned long bar, | ||
9 | unsigned long area_length); | ||
10 | void divasa_unmap_pci_bar(void __iomem *bar); | ||
11 | unsigned long divasa_get_pci_irq(unsigned char bus, | ||
12 | unsigned char func, void *pci_dev_handle); | ||
13 | unsigned long divasa_get_pci_bar(unsigned char bus, | ||
14 | unsigned char func, | ||
15 | int bar, void *pci_dev_handle); | ||
16 | byte diva_os_get_pci_bus(void *pci_dev_handle); | ||
17 | byte 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 | |||
104 | typedef struct _APPL APPL; | ||
105 | typedef struct _PLCI PLCI; | ||
106 | typedef struct _NCCI NCCI; | ||
107 | typedef struct _DIVA_CAPI_ADAPTER DIVA_CAPI_ADAPTER; | ||
108 | typedef struct _DATA_B3_DESC DATA_B3_DESC; | ||
109 | typedef struct _DATA_ACK_DESC DATA_ACK_DESC; | ||
110 | typedef struct manufacturer_profile_s MANUFACTURER_PROFILE; | ||
111 | typedef struct fax_ncpi_s FAX_NCPI; | ||
112 | typedef struct api_parse_s API_PARSE; | ||
113 | typedef struct api_save_s API_SAVE; | ||
114 | typedef struct msn_config_s MSN_CONFIG; | ||
115 | typedef struct msn_config_max_s MSN_CONFIG_MAX; | ||
116 | typedef struct msn_ld_s MSN_LD; | ||
117 | |||
118 | struct manufacturer_profile_s { | ||
119 | dword private_options; | ||
120 | dword rtp_primary_payloads; | ||
121 | dword rtp_additional_payloads; | ||
122 | }; | ||
123 | |||
124 | struct fax_ncpi_s { | ||
125 | word options; | ||
126 | word format; | ||
127 | }; | ||
128 | |||
129 | struct msn_config_s { | ||
130 | byte msn[MAX_CPN_MASK_SIZE]; | ||
131 | }; | ||
132 | |||
133 | struct msn_config_max_s { | ||
134 | MSN_CONFIG msn_conf[MAX_MSN_CONFIG]; | ||
135 | }; | ||
136 | |||
137 | struct msn_ld_s { | ||
138 | dword low; | ||
139 | dword high; | ||
140 | }; | ||
141 | |||
142 | struct api_parse_s { | ||
143 | word length; | ||
144 | byte * info; | ||
145 | }; | ||
146 | |||
147 | struct api_save_s { | ||
148 | API_PARSE parms[MAX_MSG_PARMS+1]; | ||
149 | byte info[MAX_MSG_SIZE]; | ||
150 | }; | ||
151 | |||
152 | struct _DATA_B3_DESC { | ||
153 | word Handle; | ||
154 | word Number; | ||
155 | word Flags; | ||
156 | word Length; | ||
157 | void * P; | ||
158 | }; | ||
159 | |||
160 | struct _DATA_ACK_DESC { | ||
161 | word Handle; | ||
162 | word Number; | ||
163 | }; | ||
164 | |||
165 | typedef 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!!!! */ | ||
169 | struct _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 | |||
214 | struct _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 | |||
338 | struct _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 | |||
348 | struct _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 | |||
452 | typedef struct t30_info_s T30_INFO; | ||
453 | struct 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 | |||
640 | typedef struct async_s ASYNC_FORMAT; | ||
641 | struct 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 | |||
903 | typedef struct li_config_s LI_CONFIG; | ||
904 | |||
905 | struct xconnect_card_address_s { | ||
906 | dword low; | ||
907 | dword high; | ||
908 | }; | ||
909 | |||
910 | struct xconnect_transfer_address_s { | ||
911 | struct xconnect_card_address_s card_address; | ||
912 | dword offset; | ||
913 | }; | ||
914 | |||
915 | struct 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 | |||
927 | extern LI_CONFIG *li_config_table; | ||
928 | extern 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 | |||
28 | static char *main_revision = "$Revision: 1.32.6.10 $"; | ||
29 | |||
30 | static int major; | ||
31 | |||
32 | MODULE_DESCRIPTION("Maint driver for Eicon DIVA Server cards"); | ||
33 | MODULE_AUTHOR("Cytronics & Melware, Eicon Networks"); | ||
34 | MODULE_SUPPORTED_DEVICE("DIVA card driver"); | ||
35 | MODULE_LICENSE("GPL"); | ||
36 | |||
37 | static int buffer_length = 128; | ||
38 | module_param(buffer_length, int, 0); | ||
39 | static unsigned long diva_dbg_mem = 0; | ||
40 | module_param(diva_dbg_mem, ulong, 0); | ||
41 | |||
42 | static char *DRIVERNAME = | ||
43 | "Eicon DIVA - MAINT module (http://www.melware.net)"; | ||
44 | static char *DRIVERLNAME = "diva_mnt"; | ||
45 | static char *DEVNAME = "DivasMAINT"; | ||
46 | char *DRIVERRELEASE_MNT = "2.0"; | ||
47 | |||
48 | static wait_queue_head_t msgwaitq; | ||
49 | static unsigned long opened; | ||
50 | static struct timeval start_time; | ||
51 | |||
52 | extern int mntfunc_init(int *, void **, unsigned long); | ||
53 | extern void mntfunc_finit(void); | ||
54 | extern int maint_read_write(void __user *buf, int count); | ||
55 | |||
56 | /* | ||
57 | * helper functions | ||
58 | */ | ||
59 | static 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 | */ | ||
77 | int 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 | } | ||
82 | int 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 | */ | ||
91 | void 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 | */ | ||
120 | static 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 | |||
132 | static 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 | |||
144 | static 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 | |||
157 | static 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 | |||
163 | static 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 | |||
169 | static 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 | |||
179 | static void divas_maint_unregister_chrdev(void) | ||
180 | { | ||
181 | devfs_remove(DEVNAME); | ||
182 | unregister_chrdev(major, DEVNAME); | ||
183 | } | ||
184 | |||
185 | static 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 | */ | ||
201 | void diva_maint_wakeup_read(void) | ||
202 | { | ||
203 | wake_up_interruptible(&msgwaitq); | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | * Driver Load | ||
208 | */ | ||
209 | static 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 | */ | ||
247 | static 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 | |||
255 | module_init(maint_init); | ||
256 | module_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 | |||
24 | static int debugmask; | ||
25 | |||
26 | extern void DIVA_DIDD_Read(void *, int); | ||
27 | |||
28 | extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER]; | ||
29 | |||
30 | extern char *DRIVERRELEASE_DIVAS; | ||
31 | |||
32 | static dword notify_handle; | ||
33 | static DESCRIPTOR DAdapter; | ||
34 | static DESCRIPTOR MAdapter; | ||
35 | |||
36 | /* -------------------------------------------------------------------------- | ||
37 | MAINT driver connector section | ||
38 | -------------------------------------------------------------------------- */ | ||
39 | static 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 | */ | ||
49 | void 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 | */ | ||
64 | void 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 | */ | ||
95 | void 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 | */ | ||
113 | static 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 | */ | ||
124 | static 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 | */ | ||
134 | static 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 | */ | ||
157 | static 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 | */ | ||
198 | static 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 | */ | ||
213 | int 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 | */ | ||
234 | void 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 | |||
31 | static char *main_revision = "$Revision: 1.25.6.2 $"; | ||
32 | |||
33 | static int major; | ||
34 | |||
35 | MODULE_DESCRIPTION("User IDI Interface for Eicon ISDN cards"); | ||
36 | MODULE_AUTHOR("Cytronics & Melware, Eicon Networks"); | ||
37 | MODULE_SUPPORTED_DEVICE("DIVA card driver"); | ||
38 | MODULE_LICENSE("GPL"); | ||
39 | |||
40 | typedef 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 | |||
48 | static char *DRIVERNAME = "Eicon DIVA - User IDI (http://www.melware.net)"; | ||
49 | static char *DRIVERLNAME = "diva_idi"; | ||
50 | static char *DEVNAME = "DivasIDI"; | ||
51 | char *DRIVERRELEASE_IDI = "2.0"; | ||
52 | |||
53 | extern int idifunc_init(void); | ||
54 | extern void idifunc_finit(void); | ||
55 | |||
56 | /* | ||
57 | * helper functions | ||
58 | */ | ||
59 | static 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 | */ | ||
75 | static ssize_t um_idi_read(struct file *file, char __user *buf, size_t count, | ||
76 | loff_t * offset); | ||
77 | static ssize_t um_idi_write(struct file *file, const char __user *buf, | ||
78 | size_t count, loff_t * offset); | ||
79 | static unsigned int um_idi_poll(struct file *file, poll_table * wait); | ||
80 | static int um_idi_open(struct inode *inode, struct file *file); | ||
81 | static int um_idi_release(struct inode *inode, struct file *file); | ||
82 | static int remove_entity(void *entity); | ||
83 | static void diva_um_timer_function(unsigned long data); | ||
84 | |||
85 | /* | ||
86 | * proc entry | ||
87 | */ | ||
88 | extern struct proc_dir_entry *proc_net_eicon; | ||
89 | static struct proc_dir_entry *um_idi_proc_entry = NULL; | ||
90 | |||
91 | static int | ||
92 | um_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 | |||
114 | static 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 | |||
128 | static 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 | |||
136 | static 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 | |||
146 | static void divas_idi_unregister_chrdev(void) | ||
147 | { | ||
148 | devfs_remove(DEVNAME); | ||
149 | unregister_chrdev(major, DEVNAME); | ||
150 | } | ||
151 | |||
152 | static 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 | */ | ||
168 | static 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 | */ | ||
209 | static 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 | |||
218 | module_init(divasi_init); | ||
219 | module_exit(divasi_exit); | ||
220 | |||
221 | |||
222 | /* | ||
223 | * FILE OPERATIONS | ||
224 | */ | ||
225 | |||
226 | static int | ||
227 | divas_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 | |||
234 | static ssize_t | ||
235 | um_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 | |||
287 | static int | ||
288 | divas_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 | |||
295 | static 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 | |||
315 | static ssize_t | ||
316 | um_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 | |||
374 | static 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 | |||
406 | static int um_idi_open(struct inode *inode, struct file *file) | ||
407 | { | ||
408 | return (0); | ||
409 | } | ||
410 | |||
411 | |||
412 | static 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 | |||
445 | int diva_os_get_context_size(void) | ||
446 | { | ||
447 | return (sizeof(diva_um_idi_os_context_t)); | ||
448 | } | ||
449 | |||
450 | void 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 | |||
457 | void 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 | |||
464 | static | ||
465 | void 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 | */ | ||
479 | static 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 | */ | ||
559 | void 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 | |||
571 | void 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 | |||
44 | static char *main_revision = "$Revision: 1.55.4.6 $"; | ||
45 | |||
46 | static int major; | ||
47 | |||
48 | static int dbgmask; | ||
49 | |||
50 | MODULE_DESCRIPTION("Kernel driver for Eicon DIVA Server cards"); | ||
51 | MODULE_AUTHOR("Cytronics & Melware, Eicon Networks"); | ||
52 | MODULE_LICENSE("GPL"); | ||
53 | |||
54 | module_param(dbgmask, int, 0); | ||
55 | MODULE_PARM_DESC(dbgmask, "initial debug mask"); | ||
56 | |||
57 | static char *DRIVERNAME = | ||
58 | "Eicon DIVA Server driver (http://www.melware.net)"; | ||
59 | static char *DRIVERLNAME = "divas"; | ||
60 | static char *DEVNAME = "Divas"; | ||
61 | char *DRIVERRELEASE_DIVAS = "2.0"; | ||
62 | |||
63 | extern irqreturn_t diva_os_irq_wrapper(int irq, void *context, | ||
64 | struct pt_regs *regs); | ||
65 | extern int create_divas_proc(void); | ||
66 | extern void remove_divas_proc(void); | ||
67 | extern void diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf); | ||
68 | extern int divasfunc_init(int dbgmask); | ||
69 | extern void divasfunc_exit(void); | ||
70 | |||
71 | typedef 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 | */ | ||
119 | static 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 | }; | ||
156 | MODULE_DEVICE_TABLE(pci, divas_pci_tbl); | ||
157 | |||
158 | static int divas_init_one(struct pci_dev *pdev, | ||
159 | const struct pci_device_id *ent); | ||
160 | static void __devexit divas_remove_one(struct pci_dev *pdev); | ||
161 | |||
162 | static 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 | *********************************************************/ | ||
172 | static 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 | |||
185 | void 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 | |||
197 | void 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 | -------------------------------------------------------------------------- */ | ||
209 | byte 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 | |||
215 | byte 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 | |||
221 | unsigned 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 | |||
232 | unsigned 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 | |||
259 | void 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 | |||
300 | void 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 | */ | ||
343 | static 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 | |||
355 | void 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 | */ | ||
392 | void 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 | |||
423 | int | ||
424 | diva_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 | |||
438 | void __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 | |||
445 | void divasa_unmap_pci_bar(void __iomem *bar) | ||
446 | { | ||
447 | if (bar) { | ||
448 | iounmap(bar); | ||
449 | } | ||
450 | } | ||
451 | |||
452 | /********************************************************* | ||
453 | ** I/O port access | ||
454 | *********************************************************/ | ||
455 | byte __inline__ inpp(void __iomem *addr) | ||
456 | { | ||
457 | return (inb((unsigned long) addr)); | ||
458 | } | ||
459 | |||
460 | word __inline__ inppw(void __iomem *addr) | ||
461 | { | ||
462 | return (inw((unsigned long) addr)); | ||
463 | } | ||
464 | |||
465 | void __inline__ inppw_buffer(void __iomem *addr, void *P, int length) | ||
466 | { | ||
467 | insw((unsigned long) addr, (word *) P, length >> 1); | ||
468 | } | ||
469 | |||
470 | void __inline__ outppw_buffer(void __iomem *addr, void *P, int length) | ||
471 | { | ||
472 | outsw((unsigned long) addr, (word *) P, length >> 1); | ||
473 | } | ||
474 | |||
475 | void __inline__ outppw(void __iomem *addr, word w) | ||
476 | { | ||
477 | outw(w, (unsigned long) addr); | ||
478 | } | ||
479 | |||
480 | void __inline__ outpp(void __iomem *addr, word p) | ||
481 | { | ||
482 | outb(p, (unsigned long) addr); | ||
483 | } | ||
484 | |||
485 | /* -------------------------------------------------------------------------- | ||
486 | IRQ request / remove | ||
487 | -------------------------------------------------------------------------- */ | ||
488 | int 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 | |||
495 | void diva_os_remove_irq(void *context, byte irq) | ||
496 | { | ||
497 | free_irq(irq, context); | ||
498 | } | ||
499 | |||
500 | /* -------------------------------------------------------------------------- | ||
501 | DPC framework implementation | ||
502 | -------------------------------------------------------------------------- */ | ||
503 | static 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 | |||
511 | int 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 | |||
530 | int 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 | |||
542 | int diva_os_cancel_soft_isr(diva_os_soft_isr_t * psoft_isr) | ||
543 | { | ||
544 | return (0); | ||
545 | } | ||
546 | |||
547 | void 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 | */ | ||
565 | static int | ||
566 | xdi_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 | |||
574 | static int | ||
575 | xdi_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 | */ | ||
586 | static int divas_open(struct inode *inode, struct file *file) | ||
587 | { | ||
588 | return (0); | ||
589 | } | ||
590 | |||
591 | static 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 | |||
599 | static 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 | |||
630 | static 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 | |||
661 | static 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 | |||
669 | static 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 | |||
679 | static void divas_unregister_chrdev(void) | ||
680 | { | ||
681 | devfs_remove(DEVNAME); | ||
682 | unregister_chrdev(major, DEVNAME); | ||
683 | } | ||
684 | |||
685 | static 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 | -------------------------------------------------------------------------- */ | ||
701 | static 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 | |||
762 | static 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 | -------------------------------------------------------------------------- */ | ||
780 | static 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 | -------------------------------------------------------------------------- */ | ||
845 | static 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 | |||
855 | module_init(divas_init); | ||
856 | module_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 | |||
36 | extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER]; | ||
37 | extern void divas_get_version(char *); | ||
38 | extern void diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf); | ||
39 | |||
40 | /********************************************************* | ||
41 | ** Functions for /proc interface / File operations | ||
42 | *********************************************************/ | ||
43 | |||
44 | static char *divas_proc_name = "divas"; | ||
45 | static char *adapter_dir_name = "adapter"; | ||
46 | static char *info_proc_name = "info"; | ||
47 | static char *grp_opt_proc_name = "group_optimization"; | ||
48 | static char *d_l1_down_proc_name = "dynamic_l1_down"; | ||
49 | |||
50 | /* | ||
51 | ** "divas" entry | ||
52 | */ | ||
53 | |||
54 | extern struct proc_dir_entry *proc_net_eicon; | ||
55 | static struct proc_dir_entry *divas_proc_entry = NULL; | ||
56 | |||
57 | static ssize_t | ||
58 | divas_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 | |||
96 | static ssize_t | ||
97 | divas_write(struct file *file, const char __user *buf, size_t count, loff_t * off) | ||
98 | { | ||
99 | return (-ENODEV); | ||
100 | } | ||
101 | |||
102 | static unsigned int divas_poll(struct file *file, poll_table * wait) | ||
103 | { | ||
104 | return (POLLERR); | ||
105 | } | ||
106 | |||
107 | static int divas_open(struct inode *inode, struct file *file) | ||
108 | { | ||
109 | return nonseekable_open(inode, file); | ||
110 | } | ||
111 | |||
112 | static int divas_close(struct inode *inode, struct file *file) | ||
113 | { | ||
114 | return (0); | ||
115 | } | ||
116 | |||
117 | static 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 | |||
127 | int 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 | |||
141 | void 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 | */ | ||
152 | static int | ||
153 | write_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 | */ | ||
183 | static int | ||
184 | write_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 | */ | ||
215 | static int | ||
216 | read_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 | */ | ||
239 | static int | ||
240 | read_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 | */ | ||
263 | static int | ||
264 | info_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 | */ | ||
288 | static int | ||
289 | info_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 | -------------------------------------------------------------------------- */ | ||
378 | int 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 | -------------------------------------------------------------------------- */ | ||
419 | void 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 | */ | ||
75 | typedef 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 | ||
93 | typedef 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 | */ | ||
101 | typedef 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 | */ | ||
115 | typedef 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 | ||
126 | typedef 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 | ||
139 | typedef struct _diva_didd_adapter_notify { | ||
140 | dword handle; /* Notification handle */ | ||
141 | void * callback; | ||
142 | void * context; | ||
143 | } diva_didd_adapter_notify_t; | ||
144 | typedef struct _diva_didd_add_adapter { | ||
145 | void * descriptor; | ||
146 | } diva_didd_add_adapter_t; | ||
147 | typedef struct _diva_didd_remove_adapter { | ||
148 | IDI_CALL p_request; | ||
149 | } diva_didd_remove_adapter_t; | ||
150 | typedef struct _diva_didd_read_adapter_array { | ||
151 | void * buffer; | ||
152 | dword length; | ||
153 | } diva_didd_read_adapter_array_t; | ||
154 | typedef 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 | ||
165 | typedef 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 | */ | ||
196 | typedef 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; | ||
204 | typedef int ( * SERIAL_INT_CB) (void *Context) ; | ||
205 | typedef int ( * SERIAL_DPC_CB) (void *Context) ; | ||
206 | typedef unsigned char ( * SERIAL_I_SYNC) (void *Context) ; | ||
207 | typedef 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 | */ | ||
235 | typedef 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 | } | ||
316 | parms | ||
317 | ; | ||
318 | } isdnProps ; | ||
319 | /* | ||
320 | * IDI_SYNC_REQ_PORTDRV_HOOK - signal plug/unplug (Award Cardware only) | ||
321 | */ | ||
322 | typedef void ( * PORTDRV_HOOK_CB) (void *Context, int Plug) ; | ||
323 | typedef 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) | ||
336 | typedef int ( * SLIENTRYPOINT)(void* p3SignalAPI, void* pContext); | ||
337 | typedef 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 | */ | ||
351 | typedef int ( * USB_SEND_REQ) (unsigned char PipeIndex, unsigned char Type,void *Data, int sizeData); | ||
352 | typedef int ( * USB_START_DEV) (void *Adapter, void *Ipac) ; | ||
353 | /* called from WDM */ | ||
354 | typedef void ( * USB_RECV_NOTIFY) (void *Ipac, void *msg) ; | ||
355 | typedef 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 | */ | ||
363 | typedef 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 | |||
16 | int | ||
17 | diva_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 | |||
41 | int 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 | |||
57 | int diva_data_q_get_max_length(const diva_um_idi_data_queue_t * q) | ||
58 | { | ||
59 | return (q->max_length); | ||
60 | } | ||
61 | |||
62 | void *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 | |||
72 | void | ||
73 | diva_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 | |||
86 | const 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 | |||
95 | int diva_data_q_get_segment_length(const diva_um_idi_data_queue_t * q) | ||
96 | { | ||
97 | return (q->length[q->read]); | ||
98 | } | ||
99 | |||
100 | void 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 | |||
8 | typedef 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 | |||
19 | int diva_data_q_init(diva_um_idi_data_queue_t * q, | ||
20 | int max_length, int max_segments); | ||
21 | int diva_data_q_finit(diva_um_idi_data_queue_t * q); | ||
22 | int diva_data_q_get_max_length(const diva_um_idi_data_queue_t * q); | ||
23 | void *diva_data_q_get_segment4write(diva_um_idi_data_queue_t * q); | ||
24 | void diva_data_q_ack_segment4write(diva_um_idi_data_queue_t * q, | ||
25 | int length); | ||
26 | const void *diva_data_q_get_segment4read(const diva_um_idi_data_queue_t * | ||
27 | q); | ||
28 | int diva_data_q_get_segment_length(const diva_um_idi_data_queue_t * q); | ||
29 | void 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 | ||
40 | struct _OsFileHandle_; | ||
41 | typedef long ( * OsFileIo) (struct _OsFileHandle_ *handle, | ||
42 | void *buffer, | ||
43 | long size) ; | ||
44 | typedef long ( * OsFileSeek)(struct _OsFileHandle_ *handle, | ||
45 | long position, | ||
46 | int mode) ; | ||
47 | typedef long ( * OsCardLoad)(struct _OsFileHandle_ *handle, | ||
48 | long length, | ||
49 | void * *addr) ; | ||
50 | typedef struct _OsFileHandle_ | ||
51 | { void *sysFileDesc ; | ||
52 | unsigned long sysFileSize ; | ||
53 | OsFileIo sysFileRead ; | ||
54 | OsFileSeek sysFileSeek ; | ||
55 | void *sysLoadDesc ; | ||
56 | OsCardLoad sysCardLoad ; | ||
57 | } OsFileHandle ; | ||
58 | extern OsFileHandle *OsOpenFile (char *path_name) ; | ||
59 | extern 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 | ||
97 | typedef 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; | ||
108 | typedef struct tag_dsp_combifile_directory_entry | ||
109 | { | ||
110 | word card_type_number; | ||
111 | word file_set_number; | ||
112 | } t_dsp_combifile_directory_entry; | ||
113 | typedef 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; | ||
134 | typedef 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; | ||
141 | typedef 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; | ||
149 | typedef 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; | ||
156 | typedef 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; | ||
163 | typedef 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; | ||
183 | typedef 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 | /* | ||
210 | parameters: | ||
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 | /* | ||
235 | data indications if transparent framer | ||
236 | <byte> data 0 | ||
237 | <byte> data 1 | ||
238 | ... | ||
239 | data 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 | /* | ||
249 | returns: | ||
250 | <word> time of sync (sampled from counter at 8kHz) | ||
251 | */ | ||
252 | #define DSP_UDATA_INDICATION_DCD_OFF 1 | ||
253 | /* | ||
254 | returns: | ||
255 | <word> time of DCD off (sampled from counter at 8kHz) | ||
256 | */ | ||
257 | #define DSP_UDATA_INDICATION_DCD_ON 2 | ||
258 | /* | ||
259 | returns: | ||
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 | /* | ||
267 | returns: | ||
268 | <word> time of CTS off (sampled from counter at 8kHz) | ||
269 | */ | ||
270 | #define DSP_UDATA_INDICATION_CTS_ON 4 | ||
271 | /* | ||
272 | returns: | ||
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 | /*---------------------------------------------------------------------------*/ | ||
298 | extern 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)) | ||
38 | void diva_os_set_qBri_functions (PISDN_ADAPTER IoAdapter); | ||
39 | void 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 | */ | ||
36 | void 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 | */ | ||
36 | void diva_os_prepare_pri_functions (PISDN_ADAPTER IoAdapter); | ||
37 | void 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 | |||
12 | typedef 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__ | ||
28 | dword diva_get_protocol_file_features (byte* File, | ||
29 | int offset, | ||
30 | char *IdStringBuffer, | ||
31 | dword IdBufferSize); | ||
32 | void 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 | ------------------------------------------------------------------------- */ | ||
41 | void *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 | ------------------------------------------------------------------------- */ | ||
46 | void *xdiLoadArchive (PISDN_ADAPTER IoAdapter, dword *FileLength, unsigned long MaxLoadSize) ; | ||
47 | /* -------------------------------------------------------------------------- | ||
48 | Free all system resources accessed by xdiLoadFile and xdiLoadArchive | ||
49 | -------------------------------------------------------------------------- */ | ||
50 | void 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 | |||
22 | extern char *DRIVERRELEASE_IDI; | ||
23 | |||
24 | extern void DIVA_DIDD_Read(void *, int); | ||
25 | extern int diva_user_mode_idi_create_adapter(const DESCRIPTOR *, int); | ||
26 | extern void diva_user_mode_idi_remove_adapter(int); | ||
27 | |||
28 | static dword notify_handle; | ||
29 | static DESCRIPTOR DAdapter; | ||
30 | static DESCRIPTOR MAdapter; | ||
31 | |||
32 | static void no_printf(unsigned char *x, ...) | ||
33 | { | ||
34 | /* dummy debug function */ | ||
35 | } | ||
36 | |||
37 | #include "debuglib.c" | ||
38 | |||
39 | /* | ||
40 | * stop debug | ||
41 | */ | ||
42 | static void stop_dbg(void) | ||
43 | { | ||
44 | DbgDeregister(); | ||
45 | memset(&MAdapter, 0, sizeof(MAdapter)); | ||
46 | dprintf = no_printf; | ||
47 | } | ||
48 | |||
49 | typedef struct _udiva_card { | ||
50 | struct list_head list; | ||
51 | int Id; | ||
52 | DESCRIPTOR d; | ||
53 | } udiva_card; | ||
54 | |||
55 | static LIST_HEAD(cards); | ||
56 | static diva_os_spin_lock_t ll_lock; | ||
57 | |||
58 | /* | ||
59 | * find card in list | ||
60 | */ | ||
61 | static 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 | */ | ||
83 | static 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 | */ | ||
115 | static 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 | */ | ||
135 | static void DIVA_EXIT_FUNCTION remove_all_idi_proc(void) | ||
136 | { | ||
137 | udiva_card *card; | ||
138 | diva_os_spin_lock_magic_t old_irql; | ||
139 | |||
140 | rescan: | ||
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 | */ | ||
156 | static 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 | */ | ||
183 | static 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 | */ | ||
227 | static 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 | */ | ||
242 | int 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 | */ | ||
262 | void 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" | ||
36 | extern ADAPTER * adapter[MAX_ADAPTER]; | ||
37 | extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER]; | ||
38 | void request (PISDN_ADAPTER, ENTITY *); | ||
39 | static void pcm_req (PISDN_ADAPTER, ENTITY *); | ||
40 | /* -------------------------------------------------------------------------- | ||
41 | local functions | ||
42 | -------------------------------------------------------------------------- */ | ||
43 | #define ReqFunc(N) \ | ||
44 | static void Request##N(ENTITY *e) \ | ||
45 | { if ( IoAdapters[N] ) (* IoAdapters[N]->DIRequest)(IoAdapters[N], e) ; } | ||
46 | ReqFunc(0) | ||
47 | ReqFunc(1) | ||
48 | ReqFunc(2) | ||
49 | ReqFunc(3) | ||
50 | ReqFunc(4) | ||
51 | ReqFunc(5) | ||
52 | ReqFunc(6) | ||
53 | ReqFunc(7) | ||
54 | ReqFunc(8) | ||
55 | ReqFunc(9) | ||
56 | ReqFunc(10) | ||
57 | ReqFunc(11) | ||
58 | ReqFunc(12) | ||
59 | ReqFunc(13) | ||
60 | ReqFunc(14) | ||
61 | ReqFunc(15) | ||
62 | IDI_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 | */ | ||
73 | static 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 | /*****************************************************************************/ | ||
86 | void | ||
87 | dump_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) | ||
122 | static 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 | ||
158 | void | ||
159 | dump_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(®s[ 0]), READ_DWORD(®s[ 1]), | ||
174 | READ_DWORD(®s[ 2]), READ_DWORD(®s[ 3]))) | ||
175 | DBG_FTL(("a0 0x%08x a1 0x%08x a2 0x%08x a3 0x%08x", | ||
176 | READ_DWORD(®s[ 4]), READ_DWORD(®s[ 5]), | ||
177 | READ_DWORD(®s[ 6]), READ_DWORD(®s[ 7]))) | ||
178 | DBG_FTL(("t0 0x%08x t1 0x%08x t2 0x%08x t3 0x%08x", | ||
179 | READ_DWORD(®s[ 8]), READ_DWORD(®s[ 9]), | ||
180 | READ_DWORD(®s[10]), READ_DWORD(®s[11]))) | ||
181 | DBG_FTL(("t4 0x%08x t5 0x%08x t6 0x%08x t7 0x%08x", | ||
182 | READ_DWORD(®s[12]), READ_DWORD(®s[13]), | ||
183 | READ_DWORD(®s[14]), READ_DWORD(®s[15]))) | ||
184 | DBG_FTL(("s0 0x%08x s1 0x%08x s2 0x%08x s3 0x%08x", | ||
185 | READ_DWORD(®s[16]), READ_DWORD(®s[17]), | ||
186 | READ_DWORD(®s[18]), READ_DWORD(®s[19]))) | ||
187 | DBG_FTL(("s4 0x%08x s5 0x%08x s6 0x%08x s7 0x%08x", | ||
188 | READ_DWORD(®s[20]), READ_DWORD(®s[21]), | ||
189 | READ_DWORD(®s[22]), READ_DWORD(®s[23]))) | ||
190 | DBG_FTL(("t8 0x%08x t9 0x%08x k0 0x%08x k1 0x%08x", | ||
191 | READ_DWORD(®s[24]), READ_DWORD(®s[25]), | ||
192 | READ_DWORD(®s[26]), READ_DWORD(®s[27]))) | ||
193 | DBG_FTL(("gp 0x%08x sp 0x%08x s8 0x%08x ra 0x%08x", | ||
194 | READ_DWORD(®s[28]), READ_DWORD(®s[29]), | ||
195 | READ_DWORD(®s[30]), READ_DWORD(®s[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 | -------------------------------------------------------------------------- */ | ||
203 | void 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 | --------------------------------------------------------------------- */ | ||
452 | void 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 | -------------------------------------------------------------------------- */ | ||
501 | static void | ||
502 | pcm_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 | } | ||
571 | Trapped: | ||
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 | /*------------------------------------------------------------------*/ | ||
587 | byte 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 | } | ||
595 | word 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 | } | ||
603 | void 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 | } | ||
612 | void 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 | } | ||
618 | void 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 | } | ||
626 | void 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 | } | ||
632 | void 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 | } | ||
638 | void 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 | } | ||
648 | void 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 | } | ||
654 | void 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 | /*------------------------------------------------------------------*/ | ||
664 | byte 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 | } | ||
673 | word 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 | } | ||
682 | void 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 | } | ||
701 | void 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 | } | ||
710 | void 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 | } | ||
717 | void 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 | } | ||
724 | void 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 | } | ||
743 | void 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 | /*------------------------------------------------------------------*/ | ||
756 | void 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 | } | ||
766 | void 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 | } | ||
777 | byte 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 | } | ||
794 | void 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 | } | ||
811 | byte look_req(ADAPTER * a) | ||
812 | { | ||
813 | PISDN_ADAPTER IoAdapter; | ||
814 | IoAdapter = (PISDN_ADAPTER) a->io; | ||
815 | return ((byte)IoAdapter->head) ; | ||
816 | } | ||
817 | void 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 | /*------------------------------------------------------------------*/ | ||
830 | ENTITY * 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 | } | ||
836 | void * PTR_X(ADAPTER * a, ENTITY * e) | ||
837 | { | ||
838 | return ((void *) e->X); | ||
839 | } | ||
840 | void * PTR_R(ADAPTER * a, ENTITY * e) | ||
841 | { | ||
842 | return ((void *) e->R); | ||
843 | } | ||
844 | void * PTR_P(ADAPTER * a, ENTITY * e, void * P) | ||
845 | { | ||
846 | return P; | ||
847 | } | ||
848 | void 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 | -------------------------------------------------------------------------- */ | ||
37 | typedef 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 | ||
46 | typedef 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 | ||
55 | typedef struct _diva_xdi_capi_cfg { | ||
56 | byte cfg_1; | ||
57 | } diva_xdi_capi_cfg_t; | ||
58 | /* -------------------------------------------------------------------------- | ||
59 | Main data structure kept per adapter | ||
60 | -------------------------------------------------------------------------- */ | ||
61 | struct _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 | --------------------------------------------------------------------- */ | ||
231 | struct 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 | --------------------------------------------------------------------- */ | ||
239 | struct 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 | --------------------------------------------------------------------- */ | ||
257 | extern void * PTR_P(ADAPTER * a, ENTITY * e, void * P); | ||
258 | extern void * PTR_X(ADAPTER * a, ENTITY * e); | ||
259 | extern void * PTR_R(ADAPTER * a, ENTITY * e); | ||
260 | extern void CALLBACK(ADAPTER * a, ENTITY * e); | ||
261 | extern void set_ram(void * * adr_ptr); | ||
262 | /* --------------------------------------------------------------------- | ||
263 | ram access functions for io mapped cards | ||
264 | --------------------------------------------------------------------- */ | ||
265 | byte io_in(ADAPTER * a, void * adr); | ||
266 | word io_inw(ADAPTER * a, void * adr); | ||
267 | void io_in_buffer(ADAPTER * a, void * adr, void * P, word length); | ||
268 | void io_look_ahead(ADAPTER * a, PBUFFER * RBuffer, ENTITY * e); | ||
269 | void io_out(ADAPTER * a, void * adr, byte data); | ||
270 | void io_outw(ADAPTER * a, void * adr, word data); | ||
271 | void io_out_buffer(ADAPTER * a, void * adr, void * P, word length); | ||
272 | void io_inc(ADAPTER * a, void * adr); | ||
273 | void bri_in_buffer (PISDN_ADAPTER IoAdapter, dword Pos, | ||
274 | void *Buf, dword Len); | ||
275 | int 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 | --------------------------------------------------------------------- */ | ||
280 | byte mem_in(ADAPTER * a, void * adr); | ||
281 | word mem_inw(ADAPTER * a, void * adr); | ||
282 | void mem_in_buffer(ADAPTER * a, void * adr, void * P, word length); | ||
283 | void mem_look_ahead(ADAPTER * a, PBUFFER * RBuffer, ENTITY * e); | ||
284 | void mem_out(ADAPTER * a, void * adr, byte data); | ||
285 | void mem_outw(ADAPTER * a, void * adr, word data); | ||
286 | void mem_out_buffer(ADAPTER * a, void * adr, void * P, word length); | ||
287 | void mem_inc(ADAPTER * a, void * adr); | ||
288 | void mem_in_dw (ADAPTER *a, void *addr, dword* data, int dwords); | ||
289 | void mem_out_dw (ADAPTER *a, void *addr, const dword* data, int dwords); | ||
290 | /* --------------------------------------------------------------------- | ||
291 | functions exported by io.c | ||
292 | --------------------------------------------------------------------- */ | ||
293 | extern IDI_CALL Requests[MAX_ADAPTER] ; | ||
294 | extern void DIDpcRoutine (struct _diva_os_soft_isr* psoft_isr, | ||
295 | void* context); | ||
296 | extern void request (PISDN_ADAPTER, ENTITY *) ; | ||
297 | /* --------------------------------------------------------------------- | ||
298 | trapFn helpers, used to recover debug trace from dead card | ||
299 | --------------------------------------------------------------------- */ | ||
300 | typedef struct { | ||
301 | word *buf ; | ||
302 | word cnt ; | ||
303 | word out ; | ||
304 | } Xdesc ; | ||
305 | extern void dump_trap_frame (PISDN_ADAPTER IoAdapter, byte __iomem *exception) ; | ||
306 | extern 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" | ||
39 | int diva_istream_write (void* context, | ||
40 | int Id, | ||
41 | void* data, | ||
42 | int length, | ||
43 | int final, | ||
44 | byte usr1, | ||
45 | byte usr2); | ||
46 | int 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 | ------------------------------------------------------------------- */ | ||
56 | void 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 | ------------------------------------------------------------------ */ | ||
70 | int 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 | ------------------------------------------------------------------- */ | ||
148 | int 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 | --------------------------------------------------------------------- */ | ||
224 | void 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 | |||
32 | typedef 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 | */ | ||
41 | typedef 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 | */ | ||
75 | typedef 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 | */ | ||
96 | typedef 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 | |||
101 | typedef 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 | |||
112 | typedef 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 | |||
122 | typedef 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 | |||
134 | typedef 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 | |||
155 | typedef 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 | |||
164 | typedef 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 | */ | ||
179 | typedef 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 | |||
224 | struct _diva_strace_library_interface; | ||
225 | typedef 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); | ||
229 | typedef 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); | ||
232 | typedef 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 | */ | ||
240 | typedef 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 | */ | ||
250 | typedef int (*DivaSTraceLibraryStart_proc_t)(void* hLib); | ||
251 | typedef int (*DivaSTraceLibraryFinit_proc_t)(void* hLib); | ||
252 | typedef int (*DivaSTraceMessageInput_proc_t)(void* hLib); | ||
253 | typedef 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 | */ | ||
259 | typedef 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 | */ | ||
265 | typedef 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 | */ | ||
275 | typedef int (*DivaSTraceSetDChannel_proc_t)(void* hLib, int on); | ||
276 | |||
277 | /* | ||
278 | Get overall card statistics | ||
279 | */ | ||
280 | typedef int (*DivaSTraceGetOutgoingCallStatistics_proc_t)(void* hLib); | ||
281 | typedef int (*DivaSTraceGetIncomingCallStatistics_proc_t)(void* hLib); | ||
282 | typedef int (*DivaSTraceGetModemStatistics_proc_t)(void* hLib); | ||
283 | typedef int (*DivaSTraceGetFaxStatistics_proc_t)(void* hLib); | ||
284 | typedef int (*DivaSTraceGetBLayer1Statistics_proc_t)(void* hLib); | ||
285 | typedef int (*DivaSTraceGetBLayer2Statistics_proc_t)(void* hLib); | ||
286 | typedef int (*DivaSTraceGetDLayer1Statistics_proc_t)(void* hLib); | ||
287 | typedef int (*DivaSTraceGetDLayer2Statistics_proc_t)(void* hLib); | ||
288 | |||
289 | /* | ||
290 | Call control | ||
291 | */ | ||
292 | typedef int (*DivaSTraceClearCall_proc_t)(void* hLib, int Channel); | ||
293 | |||
294 | typedef 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 | */ | ||
327 | diva_strace_library_interface_t* DivaSTraceLibraryCreateInstance (int Adapter, | ||
328 | const diva_trace_library_user_interface_t* user_proc, | ||
329 | byte* pmem); | ||
330 | dword 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 | |||
31 | void DI_lock (void) ; | ||
32 | void DI_unlock (void) ; | ||
33 | |||
34 | #ifdef NOT_YET_NEEDED | ||
35 | void DI_nttime (LARGE_INTEGER *NTtime) ; | ||
36 | void DI_ntlcltime(LARGE_INTEGER *NTtime, LARGE_INTEGER *lclNTtime) ; | ||
37 | void DI_nttimefields(LARGE_INTEGER *NTtime, TIME_FIELDS *TimeFields); | ||
38 | unsigned long DI_wintime(LARGE_INTEGER *NTtime) ; | ||
39 | |||
40 | unsigned short DiInsertProcessorNumber (int type) ; | ||
41 | void DiProcessEventLog (unsigned short id, unsigned long msgID, va_list ap); | ||
42 | |||
43 | void StartIoctlTimer (void (*Handler)(void), unsigned long msec) ; | ||
44 | void StopIoctlTimer (void) ; | ||
45 | void UnpendIoctl (DbgRequest *pDbgReq) ; | ||
46 | #endif | ||
47 | |||
48 | void 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 | |||
33 | extern 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 | */ | ||
43 | static int DivaSTraceLibraryStart (void* hLib); | ||
44 | static int DivaSTraceLibraryStop (void* hLib); | ||
45 | static int SuperTraceLibraryFinit (void* hLib); | ||
46 | static void* SuperTraceGetHandle (void* hLib); | ||
47 | static int SuperTraceMessageInput (void* hLib); | ||
48 | static int SuperTraceSetAudioTap (void* hLib, int Channel, int on); | ||
49 | static int SuperTraceSetBChannel (void* hLib, int Channel, int on); | ||
50 | static int SuperTraceSetDChannel (void* hLib, int on); | ||
51 | static int SuperTraceSetInfo (void* hLib, int on); | ||
52 | static int SuperTraceClearCall (void* hLib, int Channel); | ||
53 | static int SuperTraceGetOutgoingCallStatistics (void* hLib); | ||
54 | static int SuperTraceGetIncomingCallStatistics (void* hLib); | ||
55 | static int SuperTraceGetModemStatistics (void* hLib); | ||
56 | static int SuperTraceGetFaxStatistics (void* hLib); | ||
57 | static int SuperTraceGetBLayer1Statistics (void* hLib); | ||
58 | static int SuperTraceGetBLayer2Statistics (void* hLib); | ||
59 | static int SuperTraceGetDLayer1Statistics (void* hLib); | ||
60 | static int SuperTraceGetDLayer2Statistics (void* hLib); | ||
61 | |||
62 | /* | ||
63 | LOCAL FUNCTIONS | ||
64 | */ | ||
65 | static int ScheduleNextTraceRequest (diva_strace_context_t* pLib); | ||
66 | static int process_idi_event (diva_strace_context_t* pLib, | ||
67 | diva_man_var_header_t* pVar); | ||
68 | static int process_idi_info (diva_strace_context_t* pLib, | ||
69 | diva_man_var_header_t* pVar); | ||
70 | static int diva_modem_event (diva_strace_context_t* pLib, int Channel); | ||
71 | static int diva_fax_event (diva_strace_context_t* pLib, int Channel); | ||
72 | static int diva_line_event (diva_strace_context_t* pLib, int Channel); | ||
73 | static int diva_modem_info (diva_strace_context_t* pLib, | ||
74 | int Channel, | ||
75 | diva_man_var_header_t* pVar); | ||
76 | static int diva_fax_info (diva_strace_context_t* pLib, | ||
77 | int Channel, | ||
78 | diva_man_var_header_t* pVar); | ||
79 | static int diva_line_info (diva_strace_context_t* pLib, | ||
80 | int Channel, | ||
81 | diva_man_var_header_t* pVar); | ||
82 | static int diva_ifc_statistics (diva_strace_context_t* pLib, | ||
83 | diva_man_var_header_t* pVar); | ||
84 | static diva_man_var_header_t* get_next_var (diva_man_var_header_t* pVar); | ||
85 | static diva_man_var_header_t* find_var (diva_man_var_header_t* pVar, | ||
86 | const char* name); | ||
87 | static int diva_strace_read_int (diva_man_var_header_t* pVar, int* var); | ||
88 | static int diva_strace_read_uint (diva_man_var_header_t* pVar, dword* var); | ||
89 | static int diva_strace_read_asz (diva_man_var_header_t* pVar, char* var); | ||
90 | static int diva_strace_read_asc (diva_man_var_header_t* pVar, char* var); | ||
91 | static int diva_strace_read_ie (diva_man_var_header_t* pVar, | ||
92 | diva_trace_ie_t* var); | ||
93 | static void diva_create_parse_table (diva_strace_context_t* pLib); | ||
94 | static void diva_trace_error (diva_strace_context_t* pLib, | ||
95 | int error, const char* file, int line); | ||
96 | static void diva_trace_notify_user (diva_strace_context_t* pLib, | ||
97 | int Channel, | ||
98 | int notify_subject); | ||
99 | static 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 | */ | ||
108 | diva_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 | |||
192 | static 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 | */ | ||
203 | static 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 | |||
223 | static 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 | |||
234 | static 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 | */ | ||
245 | static 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 | */ | ||
439 | static 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 | |||
855 | static 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 | |||
1032 | static int diva_line_event (diva_strace_context_t* pLib, int Channel) { | ||
1033 | pLib->pending_line_status |= (1L << (Channel-1)); | ||
1034 | return (0); | ||
1035 | } | ||
1036 | |||
1037 | static int diva_modem_event (diva_strace_context_t* pLib, int Channel) { | ||
1038 | pLib->pending_modem_status |= (1L << (Channel-1)); | ||
1039 | return (0); | ||
1040 | } | ||
1041 | |||
1042 | static 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 | */ | ||
1052 | static 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 | */ | ||
1102 | static 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 | |||
1135 | static 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 | */ | ||
1173 | static 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 | */ | ||
1215 | static 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 | */ | ||
1234 | static 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 | |||
1249 | static 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 | |||
1331 | static 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 | |||
1395 | static 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 | |||
1475 | static 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 | |||
1852 | static 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 | */ | ||
1865 | static 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 | */ | ||
1880 | static 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 | */ | ||
1910 | static 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 | |||
1938 | static 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 | */ | ||
1974 | static 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 | */ | ||
1992 | static 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 | */ | ||
2006 | static 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 | |||
2018 | static 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 | |||
2045 | static 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 | |||
2062 | static 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 | |||
2074 | static 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 | |||
2086 | static 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 | */ | ||
2102 | static 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 | |||
2139 | static 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 | |||
2145 | static 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 | |||
2151 | static 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 | |||
2157 | static 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 | |||
2163 | static 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 | |||
2169 | static 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 | |||
2175 | static 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 | |||
2181 | static 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 | |||
2187 | dword 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 | |||
28 | void* SuperTraceOpenAdapter (int AdapterNumber); | ||
29 | int SuperTraceCloseAdapter (void* AdapterHandle); | ||
30 | int SuperTraceWrite (void* AdapterHandle, | ||
31 | const void* data, int length); | ||
32 | int SuperTraceReadRequest (void* AdapterHandle,const char* name,byte* data); | ||
33 | int SuperTraceGetNumberOfChannels (void* AdapterHandle); | ||
34 | int SuperTraceASSIGN (void* AdapterHandle, byte* data); | ||
35 | int SuperTraceREMOVE (void* AdapterHandle); | ||
36 | int SuperTraceTraceOnRequest(void* hAdapter, const char* name, byte* data); | ||
37 | int SuperTraceWriteVar (void* AdapterHandle, | ||
38 | byte* data, | ||
39 | const char* name, | ||
40 | void* var, | ||
41 | byte type, | ||
42 | byte var_length); | ||
43 | int SuperTraceExecuteRequest (void* AdapterHandle, | ||
44 | const char* name, | ||
45 | byte* data); | ||
46 | |||
47 | typedef 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 | |||
54 | typedef 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 | |||
160 | typedef 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 | /*------------------------------------------------------------------*/ | ||
104 | typedef struct mi_xlog_hdr_s MI_XLOG_HDR; | ||
105 | struct 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 | /* ===================================================================== | ||
33 | DCD_OFF Message: | ||
34 | <word> time of DCD off (sampled from counter at 8kHz) | ||
35 | DCD_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 | /* | ||
132 | returns: | ||
133 | <byte> cause | ||
134 | */ | ||
135 | /* ========================================================== | ||
136 | DLC: B2 modem configuration | ||
137 | ========================================================== */ | ||
138 | /* | ||
139 | Fields 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 | /* | ||
178 | Fields 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 | /*------------------------------------------------------------------*/ | ||
58 | static 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 | |||
75 | static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci); | ||
76 | static void set_group_ind_mask (PLCI *plci); | ||
77 | static void clear_group_ind_mask_bit (PLCI *plci, word b); | ||
78 | static byte test_group_ind_mask_bit (PLCI *plci, word b); | ||
79 | void AutomaticLaw(DIVA_CAPI_ADAPTER *); | ||
80 | word CapiRelease(word); | ||
81 | word CapiRegister(word); | ||
82 | word api_put(APPL *, CAPI_MSG *); | ||
83 | static word api_parse(byte *, word, byte *, API_PARSE *); | ||
84 | static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out); | ||
85 | static void api_load_msg(API_SAVE *in, API_PARSE *out); | ||
86 | |||
87 | word api_remove_start(void); | ||
88 | void api_remove_complete(void); | ||
89 | |||
90 | static void plci_remove(PLCI *); | ||
91 | static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a); | ||
92 | static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *); | ||
93 | |||
94 | void callback(ENTITY *); | ||
95 | |||
96 | static void control_rc(PLCI *, byte, byte, byte, byte, byte); | ||
97 | static void data_rc(PLCI *, byte); | ||
98 | static void data_ack(PLCI *, byte); | ||
99 | static void sig_ind(PLCI *); | ||
100 | static void SendInfo(PLCI *, dword, byte * *, byte); | ||
101 | static void SendSetupInfo(APPL *, PLCI *, dword, byte * *, byte); | ||
102 | static void SendSSExtInd(APPL *, PLCI * plci, dword Id, byte * * parms); | ||
103 | |||
104 | static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms); | ||
105 | |||
106 | static void nl_ind(PLCI *); | ||
107 | |||
108 | static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
109 | static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
110 | static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
111 | static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
112 | static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
113 | static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
114 | static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
115 | static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
116 | static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
117 | static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
118 | static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
119 | static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
120 | static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
121 | static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
122 | static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
123 | static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
124 | static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
125 | static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
126 | static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
127 | static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
128 | static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
129 | static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
130 | static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
131 | static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
132 | |||
133 | static word get_plci(DIVA_CAPI_ADAPTER *); | ||
134 | static void add_p(PLCI *, byte, byte *); | ||
135 | static void add_s(PLCI * plci, byte code, API_PARSE * p); | ||
136 | static void add_ss(PLCI * plci, byte code, API_PARSE * p); | ||
137 | static void add_ie(PLCI * plci, byte code, byte * p, word p_length); | ||
138 | static void add_d(PLCI *, word, byte *); | ||
139 | static void add_ai(PLCI *, API_PARSE *); | ||
140 | static word add_b1(PLCI *, API_PARSE *, word, word); | ||
141 | static word add_b23(PLCI *, API_PARSE *); | ||
142 | static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms); | ||
143 | static void sig_req(PLCI *, byte, byte); | ||
144 | static void nl_req_ncci(PLCI *, byte, byte); | ||
145 | static void send_req(PLCI *); | ||
146 | static void send_data(PLCI *); | ||
147 | static word plci_remove_check(PLCI *); | ||
148 | static void listen_check(DIVA_CAPI_ADAPTER *); | ||
149 | static byte AddInfo(byte **, byte **, byte *, byte *); | ||
150 | static byte getChannel(API_PARSE *); | ||
151 | static void IndParse(PLCI *, word *, byte **, byte); | ||
152 | static byte ie_compare(byte *, byte *); | ||
153 | static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *); | ||
154 | static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER *,word); | ||
155 | |||
156 | /* | ||
157 | XON protocol helpers | ||
158 | */ | ||
159 | static void channel_flow_control_remove (PLCI * plci); | ||
160 | static void channel_x_off (PLCI * plci, byte ch, byte flag); | ||
161 | static void channel_x_on (PLCI * plci, byte ch); | ||
162 | static void channel_request_xon (PLCI * plci, byte ch); | ||
163 | static void channel_xmit_xon (PLCI * plci); | ||
164 | static int channel_can_xon (PLCI * plci, byte ch); | ||
165 | static void channel_xmit_extended_xon (PLCI * plci); | ||
166 | |||
167 | static byte SendMultiIE(PLCI * plci, dword Id, byte * * parms, byte ie_type, dword info_mask, byte setupParse); | ||
168 | static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte); | ||
169 | static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *); | ||
170 | static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER * ); | ||
171 | static void VoiceChannelOff(PLCI *plci); | ||
172 | static void adv_voice_write_coefs (PLCI *plci, word write_command); | ||
173 | static void adv_voice_clear_config (PLCI *plci); | ||
174 | |||
175 | static word get_b1_facilities (PLCI * plci, byte b1_resource); | ||
176 | static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities); | ||
177 | static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities); | ||
178 | static word adjust_b_process (dword Id, PLCI *plci, byte Rc); | ||
179 | static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command); | ||
180 | static void adjust_b_restore (dword Id, PLCI *plci, byte Rc); | ||
181 | static void reset_b3_command (dword Id, PLCI *plci, byte Rc); | ||
182 | static void select_b_command (dword Id, PLCI *plci, byte Rc); | ||
183 | static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc); | ||
184 | static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc); | ||
185 | static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc); | ||
186 | static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc); | ||
187 | static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc); | ||
188 | static void hold_save_command (dword Id, PLCI *plci, byte Rc); | ||
189 | static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc); | ||
190 | static void init_b1_config (PLCI *plci); | ||
191 | static void clear_b1_config (PLCI *plci); | ||
192 | |||
193 | static void dtmf_command (dword Id, PLCI *plci, byte Rc); | ||
194 | static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg); | ||
195 | static void dtmf_confirmation (dword Id, PLCI *plci); | ||
196 | static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length); | ||
197 | static void dtmf_parameter_write (PLCI *plci); | ||
198 | |||
199 | |||
200 | static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id); | ||
201 | static void mixer_set_bchannel_id (PLCI *plci, byte *chi); | ||
202 | static void mixer_clear_config (PLCI *plci); | ||
203 | static void mixer_notify_update (PLCI *plci, byte others); | ||
204 | static void mixer_command (dword Id, PLCI *plci, byte Rc); | ||
205 | static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg); | ||
206 | static void mixer_indication_coefs_set (dword Id, PLCI *plci); | ||
207 | static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length); | ||
208 | static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length); | ||
209 | static void mixer_remove (PLCI *plci); | ||
210 | |||
211 | |||
212 | static void ec_command (dword Id, PLCI *plci, byte Rc); | ||
213 | static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg); | ||
214 | static void ec_indication (dword Id, PLCI *plci, byte *msg, word length); | ||
215 | |||
216 | |||
217 | static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc); | ||
218 | static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc); | ||
219 | |||
220 | |||
221 | static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic); | ||
222 | static void diva_free_dma_descriptor (PLCI *plci, int nr); | ||
223 | |||
224 | /*------------------------------------------------------------------*/ | ||
225 | /* external function prototypes */ | ||
226 | /*------------------------------------------------------------------*/ | ||
227 | |||
228 | extern byte MapController (byte); | ||
229 | extern byte UnMapController (byte); | ||
230 | #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id))) | ||
231 | #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id))) | ||
232 | |||
233 | void sendf(APPL *, word, dword, word, byte *, ...); | ||
234 | void * TransmitBufferSet(APPL * appl, dword ref); | ||
235 | void * TransmitBufferGet(APPL * appl, void * p); | ||
236 | void TransmitBufferFree(APPL * appl, void * p); | ||
237 | void * ReceiveBufferGet(APPL * appl, int Num); | ||
238 | |||
239 | int fax_head_line_time (char *buffer); | ||
240 | |||
241 | |||
242 | /*------------------------------------------------------------------*/ | ||
243 | /* Global data definitions */ | ||
244 | /*------------------------------------------------------------------*/ | ||
245 | extern byte max_adapter; | ||
246 | extern byte max_appl; | ||
247 | extern DIVA_CAPI_ADAPTER * adapter; | ||
248 | extern APPL * application; | ||
249 | |||
250 | |||
251 | |||
252 | |||
253 | |||
254 | |||
255 | |||
256 | static byte remove_started = FALSE; | ||
257 | static PLCI dummy_plci; | ||
258 | |||
259 | |||
260 | static 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 | |||
293 | static 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 | |||
326 | static 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 | |||
368 | static byte v120_default_header[] = | ||
369 | { | ||
370 | |||
371 | 0x83 /* Ext, BR , res, res, C2 , C1 , B , F */ | ||
372 | |||
373 | }; | ||
374 | |||
375 | static 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 | |||
387 | word 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 | |||
596 | word 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 | |||
635 | void 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 | |||
667 | void 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 | |||
684 | word 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 | |||
718 | static 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 | |||
731 | static 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 | |||
753 | static 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 | |||
779 | static dword ncci_mapping_bug = 0; | ||
780 | |||
781 | static 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 | |||
855 | static 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 | |||
920 | static 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 | |||
947 | static 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 | |||
1020 | static 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 | |||
1050 | static 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 | |||
1096 | static 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 | |||
1104 | static void clear_group_ind_mask_bit (PLCI *plci, word b) | ||
1105 | { | ||
1106 | plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f)); | ||
1107 | } | ||
1108 | |||
1109 | static 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 | |||
1118 | static 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 | |||
1126 | static 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 | |||
1136 | static void set_c_ind_mask_bit (PLCI *plci, word b) | ||
1137 | { | ||
1138 | plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f)); | ||
1139 | } | ||
1140 | |||
1141 | static void clear_c_ind_mask_bit (PLCI *plci, word b) | ||
1142 | { | ||
1143 | plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f)); | ||
1144 | } | ||
1145 | |||
1146 | static 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 | |||
1151 | static void dump_c_ind_mask (PLCI *plci) | ||
1152 | { | ||
1153 | static 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 | |||
1198 | byte 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 | |||
1415 | byte 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 | |||
1571 | byte 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 | |||
1577 | byte 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 | |||
1632 | byte 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 | |||
1659 | byte 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 | |||
1708 | byte 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 | |||
1817 | byte 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 | |||
1823 | byte 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 | |||
1853 | byte 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 | |||
2603 | byte 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 | |||
2609 | byte 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 | |||
2843 | byte 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 | |||
2958 | byte 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 | |||
2978 | byte 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 | |||
3034 | byte 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 | |||
3090 | byte 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 | |||
3167 | byte 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 | |||
3200 | byte 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 | |||
3241 | byte 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 | |||
3265 | byte 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 | |||
3299 | byte 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 | |||
3418 | byte 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 | |||
3746 | byte 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 | |||
3821 | void 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 | |||
4022 | capi_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 | |||
4078 | void 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 | |||
4744 | void 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 | |||
4780 | void 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 | |||
4806 | void 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 | |||
6100 | static 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 | |||
6174 | void 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 | |||
6350 | byte 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 | |||
6423 | static 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 | |||
6469 | void 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 | |||
7251 | word 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 | |||
7329 | static 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 | /*------------------------------------------------------------------*/ | ||
7341 | static 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 | /*------------------------------------------------------------------*/ | ||
7349 | static 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 | /*------------------------------------------------------------------*/ | ||
7365 | static 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 | |||
7384 | static 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 | |||
7410 | void 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 | |||
7428 | void 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 | |||
7449 | word 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 | |||
7913 | word 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 | /*----------------------------------------------------------------*/ | ||
8551 | static 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 | |||
8688 | void 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 | |||
8710 | void 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 | |||
8732 | void 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 | |||
8788 | void 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 | |||
8867 | void 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 | |||
8910 | void 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 | |||
8995 | byte 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 | |||
9004 | word 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 | |||
9018 | static 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 | |||
9072 | void 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 | |||
9090 | void 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 | |||
9103 | word 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 | |||
9199 | void 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 | ------------------------------------------------------------------- */ | ||
9223 | static 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 | ------------------------------------------------------------------- */ | ||
9244 | static 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 */ | ||
9293 | void 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 */ | ||
9317 | word 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 | |||
9434 | static 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 | |||
9468 | static 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 | |||
9483 | static 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 | |||
9570 | static 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 | |||
9608 | static 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 | |||
9641 | static 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 | |||
9657 | static 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 | |||
9670 | static 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 | |||
9681 | static 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 | |||
9691 | static 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 | |||
9728 | static 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 | |||
9899 | static 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 | |||
10097 | static 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 | |||
10120 | static 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 | |||
10170 | static 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 | |||
10189 | static 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 | |||
10200 | static 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 | |||
10209 | static 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 | |||
10219 | static 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 | |||
10262 | LI_CONFIG *li_config_table; | ||
10263 | word 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 | |||
10276 | static 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 | |||
10375 | static 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 | |||
10430 | static 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 | |||
10491 | static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER *a) | ||
10492 | { | ||
10493 | static 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 | |||
10740 | static 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 | |||
10752 | static 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 | |||
10798 | static 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 | |||
10838 | static 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 | |||
10852 | static 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 | |||
10889 | static 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 | |||
10901 | static 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 | |||
11239 | static 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 | |||
11312 | static 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 | |||
11376 | static 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 | |||
11389 | static 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 | |||
11414 | static 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 | |||
11497 | static 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 | |||
11624 | static 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 | |||
11767 | static 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 | |||
11875 | static 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 | |||
11896 | static 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 | |||
11959 | static 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 | |||
12022 | static 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 | |||
12425 | static 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 | |||
12487 | static 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 | |||
12530 | static 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 | |||
12539 | static 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 | |||
12559 | static 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 | |||
12613 | static 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 (¶meter_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 (¶meter_buffer[4], w); | ||
12628 | add_p (plci, FTY, parameter_buffer); | ||
12629 | sig_req (plci, TEL_CTRL, 0); | ||
12630 | send_req (plci); | ||
12631 | } | ||
12632 | |||
12633 | |||
12634 | static 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 | |||
12647 | static 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 | |||
12656 | static 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 | |||
12666 | static 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 | |||
12703 | static 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 | |||
12816 | static 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 | |||
13006 | static 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 | |||
13062 | static 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 | |||
13217 | static 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 | |||
13279 | static 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 | |||
13288 | static 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 | |||
13298 | static 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 | |||
13344 | static 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 | |||
13388 | static 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 | |||
13420 | static 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 | |||
13525 | static 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 | |||
13559 | static 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 | |||
13570 | static 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 | |||
13922 | static 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 | |||
13944 | static 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 | |||
13990 | static 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 | |||
14030 | static 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 | |||
14089 | static 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 | |||
14138 | static 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 | |||
14178 | static 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 | |||
14229 | static 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 | |||
14277 | static 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 | |||
14320 | static 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 | |||
14373 | static 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 | |||
14427 | static 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 | |||
14468 | static 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 | |||
14507 | static 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 | |||
14533 | static 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 | ----------------------------------------------------------------- */ | ||
14567 | static 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 | |||
14578 | static 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 | |||
14585 | static 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 | |||
14594 | static 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 | |||
14604 | static 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 | */ | ||
14630 | static 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 | |||
14660 | static 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 | |||
14683 | static 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 | |||
14717 | static 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 | /**********************************************************************************/ | ||
14732 | static 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 */ | ||
14848 | word 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 | |||
14899 | static 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 | |||
14987 | static 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 | |||
15021 | static 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 */ | ||
69 | typedef struct mp_xcptcontext_s MP_XCPTC; | ||
70 | struct 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 */ | ||
82 | struct 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 | |||
19 | extern 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 | |||
24 | extern void DIVA_DIDD_Read(void *, int); | ||
25 | |||
26 | static dword notify_handle; | ||
27 | static DESCRIPTOR DAdapter; | ||
28 | static DESCRIPTOR MAdapter; | ||
29 | static DESCRIPTOR MaintDescriptor = | ||
30 | { IDI_DIMAINT, 0, 0, (IDI_CALL) diva_maint_prtComp }; | ||
31 | |||
32 | extern int diva_os_copy_to_user(void *os_handle, void __user *dst, | ||
33 | const void *src, int length); | ||
34 | extern int diva_os_copy_from_user(void *os_handle, void *dst, | ||
35 | const void __user *src, int length); | ||
36 | |||
37 | static void no_printf(unsigned char *x, ...) | ||
38 | { | ||
39 | /* dummy debug function */ | ||
40 | } | ||
41 | |||
42 | #include "debuglib.c" | ||
43 | |||
44 | /* | ||
45 | * DIDD callback function | ||
46 | */ | ||
47 | static 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 | */ | ||
75 | static 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 | */ | ||
117 | static 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 | */ | ||
136 | int 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 | */ | ||
303 | int 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 | */ | ||
351 | void 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 | |||
20 | static void *diva_xdiLoadFileFile = NULL; | ||
21 | static dword diva_xdiLoadFileLength = 0; | ||
22 | |||
23 | /* | ||
24 | ** IMPORTS | ||
25 | */ | ||
26 | extern void prepare_qBri_functions(PISDN_ADAPTER IoAdapter); | ||
27 | extern void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter); | ||
28 | extern void diva_xdi_display_adapter_features(int card); | ||
29 | extern void diva_add_slave_adapter(diva_os_xdi_adapter_t * a); | ||
30 | |||
31 | extern int qBri_FPGA_download(PISDN_ADAPTER IoAdapter); | ||
32 | extern void start_qBri_hardware(PISDN_ADAPTER IoAdapter); | ||
33 | |||
34 | extern int diva_card_read_xlog(diva_os_xdi_adapter_t * a); | ||
35 | |||
36 | /* | ||
37 | ** LOCALS | ||
38 | */ | ||
39 | static unsigned long _4bri_bar_length[4] = { | ||
40 | 0x100, | ||
41 | 0x100, /* I/O */ | ||
42 | MQ_MEMORY_SIZE, | ||
43 | 0x2000 | ||
44 | }; | ||
45 | static unsigned long _4bri_v2_bar_length[4] = { | ||
46 | 0x100, | ||
47 | 0x100, /* I/O */ | ||
48 | MQ2_MEMORY_SIZE, | ||
49 | 0x10000 | ||
50 | }; | ||
51 | static unsigned long _4bri_v2_bri_bar_length[4] = { | ||
52 | 0x100, | ||
53 | 0x100, /* I/O */ | ||
54 | BRI2_MEMORY_SIZE, | ||
55 | 0x10000 | ||
56 | }; | ||
57 | |||
58 | |||
59 | static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t * a); | ||
60 | static int _4bri_get_serial_number(diva_os_xdi_adapter_t * a); | ||
61 | static int diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a, | ||
62 | diva_xdi_um_cfg_cmd_t * cmd, | ||
63 | int length); | ||
64 | static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t * a); | ||
65 | static int diva_4bri_write_fpga_image(diva_os_xdi_adapter_t * a, | ||
66 | byte * data, dword length); | ||
67 | static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter); | ||
68 | static int diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter, | ||
69 | dword address, | ||
70 | const byte * data, | ||
71 | dword length, dword limit); | ||
72 | static int diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter, | ||
73 | dword start_address, dword features); | ||
74 | static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter); | ||
75 | static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t * a); | ||
76 | |||
77 | static 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 | |||
90 | static 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 | |||
101 | static 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 | */ | ||
143 | int 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 | */ | ||
469 | static 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 | |||
529 | static 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 | */ | ||
581 | static 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 | |||
626 | static int | ||
627 | diva_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 | |||
818 | void *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 | |||
832 | void diva_os_set_qBri_functions(PISDN_ADAPTER IoAdapter) | ||
833 | { | ||
834 | } | ||
835 | |||
836 | void diva_os_set_qBri2_functions(PISDN_ADAPTER IoAdapter) | ||
837 | { | ||
838 | } | ||
839 | |||
840 | static int | ||
841 | diva_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 | |||
857 | static 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 | |||
908 | static int | ||
909 | diva_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 | |||
932 | static int | ||
933 | diva_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 | |||
1009 | static 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 | |||
1059 | static 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 | |||
1079 | static 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 | |||
6 | int 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 | */ | ||
23 | extern void prepare_maestra_functions(PISDN_ADAPTER IoAdapter); | ||
24 | extern void diva_xdi_display_adapter_features(int card); | ||
25 | extern int diva_card_read_xlog(diva_os_xdi_adapter_t * a); | ||
26 | |||
27 | /* | ||
28 | ** LOCALS | ||
29 | */ | ||
30 | static int bri_bar_length[3] = { | ||
31 | 0x80, | ||
32 | 0x80, | ||
33 | 0x20 | ||
34 | }; | ||
35 | static int diva_bri_cleanup_adapter(diva_os_xdi_adapter_t * a); | ||
36 | static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t * a); | ||
37 | static int diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter *a, | ||
38 | diva_xdi_um_cfg_cmd_t * cmd, int length); | ||
39 | static int diva_bri_reregister_io(diva_os_xdi_adapter_t * a); | ||
40 | static int diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter); | ||
41 | static int diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter, | ||
42 | dword address, | ||
43 | const byte * data, dword length); | ||
44 | static int diva_bri_start_adapter(PISDN_ADAPTER IoAdapter, | ||
45 | dword start_address, dword features); | ||
46 | static int diva_bri_stop_adapter(diva_os_xdi_adapter_t * a); | ||
47 | |||
48 | static 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 | */ | ||
74 | int 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 | |||
267 | static 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 | |||
324 | void diva_os_prepare_maestra_functions(PISDN_ADAPTER IoAdapter) | ||
325 | { | ||
326 | } | ||
327 | |||
328 | /* | ||
329 | ** Get serial number | ||
330 | */ | ||
331 | static 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 | */ | ||
363 | static 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 | */ | ||
394 | static int | ||
395 | diva_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 | |||
515 | static 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 | |||
602 | static int | ||
603 | diva_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 | |||
630 | static int | ||
631 | diva_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 | |||
747 | static 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 | */ | ||
770 | static 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 | |||
6 | int 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 | |||
30 | extern int diva_card_read_xlog(diva_os_xdi_adapter_t * a); | ||
31 | |||
32 | /* | ||
33 | ** IMPORTS | ||
34 | */ | ||
35 | extern void prepare_pri_functions(PISDN_ADAPTER IoAdapter); | ||
36 | extern void prepare_pri2_functions(PISDN_ADAPTER IoAdapter); | ||
37 | extern void diva_xdi_display_adapter_features(int card); | ||
38 | |||
39 | static int diva_pri_cleanup_adapter(diva_os_xdi_adapter_t * a); | ||
40 | static int diva_pri_cmd_card_proc(struct _diva_os_xdi_adapter *a, | ||
41 | diva_xdi_um_cfg_cmd_t * cmd, int length); | ||
42 | static int pri_get_serial_number(diva_os_xdi_adapter_t * a); | ||
43 | static int diva_pri_stop_adapter(diva_os_xdi_adapter_t * a); | ||
44 | static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t * a); | ||
45 | |||
46 | /* | ||
47 | ** Check card revision | ||
48 | */ | ||
49 | static 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 | |||
59 | static 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 | */ | ||
94 | int 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 | |||
259 | static 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 | */ | ||
332 | static 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 | |||
406 | static int | ||
407 | diva_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 | |||
431 | static int | ||
432 | diva_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 | |||
524 | static 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 | */ | ||
548 | static 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 | */ | ||
600 | static int | ||
601 | diva_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 | */ | ||
763 | static 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 | |||
899 | void diva_os_prepare_pri2_functions(PISDN_ADAPTER IoAdapter) | ||
900 | { | ||
901 | } | ||
902 | |||
903 | void diva_os_prepare_pri_functions(PISDN_ADAPTER IoAdapter) | ||
904 | { | ||
905 | } | ||
906 | |||
907 | /* | ||
908 | ** Checks presence of DSP on board | ||
909 | */ | ||
910 | static int | ||
911 | dsp_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 | */ | ||
954 | static 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 | |||
6 | int 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 | /*------------------------------------------------------------------*/ | ||
31 | typedef 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 | /*------------------------------------------------------------------*/ | ||
38 | struct 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 | /* | ||
442 | DLC of PIAFS : | ||
443 | Byte | 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 | ||
715 | to | ||
716 | 1111 1111 | ||
717 | F1H - Reserved for network operator use | ||
718 | to | ||
719 | FFH*/ | ||
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 | ||
71 | struct 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 | }; | ||
83 | struct 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 | }; | ||
95 | struct L2Struc { | ||
96 | dword XTotal; | ||
97 | dword RTotal; | ||
98 | word XError; | ||
99 | word RError; | ||
100 | }; | ||
101 | struct OSStruc { | ||
102 | dword free_n; | ||
103 | }; | ||
104 | typedef 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; | ||
115 | typedef 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) | ||
127 | struct 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 | ||
138 | struct 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 | ||
150 | struct 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 | |||
152 | extern int sprintf(char *, const char*, ...); | ||
153 | |||
154 | typedef void* LIST_ENTRY; | ||
155 | |||
156 | typedef char DEVICE_NAME[64]; | ||
157 | typedef struct _ISDN_ADAPTER ISDN_ADAPTER; | ||
158 | typedef struct _ISDN_ADAPTER* PISDN_ADAPTER; | ||
159 | |||
160 | typedef 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 | |||
167 | typedef struct e_info_s E_INFO ; | ||
168 | |||
169 | typedef char diva_os_dependent_devica_name_t[64]; | ||
170 | typedef void* PDEVICE_OBJECT; | ||
171 | |||
172 | struct _diva_os_soft_isr; | ||
173 | struct _diva_os_timer; | ||
174 | struct _ISDN_ADAPTER; | ||
175 | |||
176 | void diva_log_info(unsigned char *, ...); | ||
177 | |||
178 | /* | ||
179 | ** XDI DIDD Interface | ||
180 | */ | ||
181 | void diva_xdi_didd_register_adapter (int card); | ||
182 | void diva_xdi_didd_remove_adapter (int card); | ||
183 | |||
184 | /* | ||
185 | ** memory allocation | ||
186 | */ | ||
187 | static __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 | } | ||
196 | static __inline__ void diva_os_free (unsigned long flags, void* ptr) | ||
197 | { | ||
198 | vfree(ptr); | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | ** use skbuffs for message buffer | ||
203 | */ | ||
204 | typedef struct sk_buff diva_os_message_buffer_s; | ||
205 | diva_os_message_buffer_s *diva_os_alloc_message_buffer(unsigned long size, void **data_buf); | ||
206 | void 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 | */ | ||
213 | static __inline__ void diva_os_sleep(dword mSec) | ||
214 | { | ||
215 | msleep(mSec); | ||
216 | } | ||
217 | static __inline__ void diva_os_wait(dword mSec) | ||
218 | { | ||
219 | mdelay(mSec); | ||
220 | } | ||
221 | |||
222 | /* | ||
223 | ** PCI Configuration space access | ||
224 | */ | ||
225 | void PCIwrite (byte bus, byte func, int offset, void* data, int length, void* pci_dev_handle); | ||
226 | void PCIread (byte bus, byte func, int offset, void* data, int length, void* pci_dev_handle); | ||
227 | |||
228 | /* | ||
229 | ** I/O Port utilities | ||
230 | */ | ||
231 | int 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 | */ | ||
236 | byte inpp (void __iomem *); | ||
237 | word inppw (void __iomem *); | ||
238 | void inppw_buffer (void __iomem *, void*, int); | ||
239 | void outppw (void __iomem *, word); | ||
240 | void outppw_buffer (void __iomem * , void*, int); | ||
241 | void outpp (void __iomem *, word); | ||
242 | |||
243 | /* | ||
244 | ** IRQ | ||
245 | */ | ||
246 | typedef 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; | ||
251 | int diva_os_register_irq (void* context, byte irq, const char* name); | ||
252 | void diva_os_remove_irq (void* context, byte irq); | ||
253 | |||
254 | #define diva_os_in_irq() in_irq() | ||
255 | |||
256 | /* | ||
257 | ** Spin Lock framework | ||
258 | */ | ||
259 | typedef long diva_os_spin_lock_magic_t; | ||
260 | typedef spinlock_t diva_os_spin_lock_t; | ||
261 | static __inline__ int diva_os_initialize_spin_lock (spinlock_t *lock, void * unused) { \ | ||
262 | spin_lock_init (lock); return(0); } | ||
263 | static __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); } | ||
266 | static __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 | */ | ||
275 | typedef int (*diva_os_isr_callback_t)(struct _ISDN_ADAPTER*); | ||
276 | typedef void (*diva_os_soft_isr_callback_t)(struct _diva_os_soft_isr* psoft_isr, void* context); | ||
277 | |||
278 | typedef 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 | |||
285 | int diva_os_initialize_soft_isr (diva_os_soft_isr_t* psoft_isr, diva_os_soft_isr_callback_t callback, void* callback_context); | ||
286 | int diva_os_schedule_soft_isr (diva_os_soft_isr_t* psoft_isr); | ||
287 | int diva_os_cancel_soft_isr (diva_os_soft_isr_t* psoft_isr); | ||
288 | void diva_os_remove_soft_isr (diva_os_soft_isr_t* psoft_isr); | ||
289 | |||
290 | /* | ||
291 | Get time service | ||
292 | */ | ||
293 | void diva_os_get_time (dword* sec, dword* usec); | ||
294 | |||
295 | /* | ||
296 | ** atomic operation, fake because we use threads | ||
297 | */ | ||
298 | typedef int diva_os_atomic_t; | ||
299 | static diva_os_atomic_t __inline__ | ||
300 | diva_os_atomic_increment(diva_os_atomic_t* pv) | ||
301 | { | ||
302 | *pv += 1; | ||
303 | return (*pv); | ||
304 | } | ||
305 | static diva_os_atomic_t __inline__ | ||
306 | diva_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 | |||
348 | static inline __u16 GET_WORD(void *addr) | ||
349 | { | ||
350 | return le16_to_cpu(*(__le16 *)addr); | ||
351 | } | ||
352 | static inline __u32 GET_DWORD(void *addr) | ||
353 | { | ||
354 | return le32_to_cpu(*(__le32 *)addr); | ||
355 | } | ||
356 | static inline void PUT_WORD(void *addr, __u16 v) | ||
357 | { | ||
358 | *(__le16 *)addr = cpu_to_le16(v); | ||
359 | } | ||
360 | static 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 | */ | ||
26 | struct 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 | }; | ||
45 | typedef 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; | ||
55 | typedef 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; | ||
64 | typedef 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 | -------------------------------------------------------------------------- */ | ||
47 | static 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 | -------------------------------------------------------------------------- */ | ||
100 | static 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 | -------------------------------------------------------------------------- */ | ||
128 | void 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 | -------------------------------------------------------------------------- */ | ||
146 | static 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 | |||
186 | static 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 | |||
275 | int 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 | |||
362 | static int load_qBri_hardware (PISDN_ADAPTER IoAdapter) { | ||
363 | return (0); | ||
364 | } | ||
365 | |||
366 | /* -------------------------------------------------------------------------- | ||
367 | Card ISR | ||
368 | -------------------------------------------------------------------------- */ | ||
369 | static 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 | -------------------------------------------------------------------------- */ | ||
413 | static 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 | -------------------------------------------------------------------------- */ | ||
435 | static 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 | |||
467 | static 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 | |||
476 | static 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 | |||
487 | void 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 | |||
496 | void 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 | -------------------------------------------------------------------------- */ | ||
43 | static 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 | --------------------------------------------------------------------- */ | ||
104 | static 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 | --------------------------------------------------------------------- */ | ||
112 | static 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 | } | ||
122 | static int load_bri_hardware (PISDN_ADAPTER IoAdapter) { | ||
123 | return (0); | ||
124 | } | ||
125 | /******************************************************************************/ | ||
126 | static 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 | -------------------------------------------------------------------------- */ | ||
148 | static 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 | ------------------------------------------------------------------------- */ | ||
163 | void 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 | ------------------------------------------------------------------------- */ | ||
43 | static dword pri_ram_offset (ADAPTER* a) { | ||
44 | return ((dword)MP_SHARED_RAM_OFFSET); | ||
45 | } | ||
46 | /* ------------------------------------------------------------------------- | ||
47 | Recovery XLOG buffer from the card | ||
48 | ------------------------------------------------------------------------- */ | ||
49 | static 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 | ------------------------------------------------------------------------- */ | ||
91 | static 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 | ------------------------------------------------------------------------- */ | ||
102 | static 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 | } | ||
125 | static int load_pri_hardware (PISDN_ADAPTER IoAdapter) { | ||
126 | return (0); | ||
127 | } | ||
128 | /* -------------------------------------------------------------------------- | ||
129 | PRI Adapter interrupt Service Routine | ||
130 | -------------------------------------------------------------------------- */ | ||
131 | static 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 | ------------------------------------------------------------------------- */ | ||
152 | static 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 | ------------------------------------------------------------------------- */ | ||
162 | static 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 | ------------------------------------------------------------------------- */ | ||
192 | void 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 | ------------------------------------------------------------------------- */ | ||
200 | void 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: | ||
31 | OFFSET 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 | */ | ||
57 | typedef 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 | */ | ||
61 | typedef 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 | */ | ||
66 | typedef 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 | */ | ||
71 | typedef word (*diva_prt_proc_t)(char *, ...); | ||
72 | typedef void (*diva_task_set_prt_proc_t)(diva_prt_proc_t fn); | ||
73 | /* | ||
74 | This function is called to set task PID | ||
75 | */ | ||
76 | typedef void (*diva_task_set_pid_proc_t)(dword id); | ||
77 | /* | ||
78 | This function is called for run-time task init | ||
79 | */ | ||
80 | typedef int (*diva_task_run_time_init_proc_t)(void*, dword); | ||
81 | /* | ||
82 | This function is called from system scheduler or from timer | ||
83 | */ | ||
84 | typedef void (*diva_task_callback_proc_t)(void); | ||
85 | /* | ||
86 | This callback is used by task to get current time im mS | ||
87 | */ | ||
88 | typedef dword (*diva_task_get_tick_count_proc_t)(void); | ||
89 | typedef void (*diva_task_set_get_time_proc_t)(\ | ||
90 | diva_task_get_tick_count_proc_t fn); | ||
91 | typedef 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 | */ | ||
106 | typedef 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 | -------------------------------------------------------------------------- */ | ||
19 | extern void diva_os_wakeup_read(void *os_context); | ||
20 | extern void diva_os_wakeup_close(void *os_context); | ||
21 | /* -------------------------------------------------------------------------- | ||
22 | LOCALS | ||
23 | -------------------------------------------------------------------------- */ | ||
24 | static LIST_HEAD(adapter_q); | ||
25 | static diva_os_spin_lock_t adapter_lock; | ||
26 | |||
27 | static diva_um_idi_adapter_t *diva_um_idi_find_adapter(dword nr); | ||
28 | static void cleanup_adapter(diva_um_idi_adapter_t * a); | ||
29 | static void cleanup_entity(divas_um_idi_entity_t * e); | ||
30 | static int diva_user_mode_idi_adapter_features(diva_um_idi_adapter_t * a, | ||
31 | diva_um_idi_adapter_features_t | ||
32 | * features); | ||
33 | static int process_idi_request(divas_um_idi_entity_t * e, | ||
34 | const diva_um_idi_req_hdr_t * req); | ||
35 | static int process_idi_rc(divas_um_idi_entity_t * e, byte rc); | ||
36 | static int process_idi_ind(divas_um_idi_entity_t * e, byte ind); | ||
37 | static int write_return_code(divas_um_idi_entity_t * e, byte rc); | ||
38 | |||
39 | /* -------------------------------------------------------------------------- | ||
40 | MAIN | ||
41 | -------------------------------------------------------------------------- */ | ||
42 | int 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 | -------------------------------------------------------------------------- */ | ||
51 | static int | ||
52 | diva_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 | -------------------------------------------------------------------------- */ | ||
83 | void 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 | -------------------------------------------------------------------------- */ | ||
103 | void 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 | ------------------------------------------------------------------------- */ | ||
121 | int 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 | ------------------------------------------------------------------------ */ | ||
150 | static 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 | ------------------------------------------------------------------------ */ | ||
169 | static 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 | ------------------------------------------------------------------------ */ | ||
189 | static 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 | ------------------------------------------------------------------------ */ | ||
208 | void *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 | ------------------------------------------------------------------------ */ | ||
272 | int 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 | -------------------------------------------------------------------------- */ | ||
301 | int 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 | |||
381 | int 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 | -------------------------------------------------------------------------- */ | ||
491 | static 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 | |||
532 | static 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 | |||
624 | static 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 | |||
677 | static 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 | -------------------------------------------------------------------------- */ | ||
733 | static 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 | -------------------------------------------------------------------------- */ | ||
759 | int 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 | |||
799 | void *diva_um_id_get_os_context(void *entity) | ||
800 | { | ||
801 | return (((divas_um_idi_entity_t *) entity)->os_context); | ||
802 | } | ||
803 | |||
804 | int 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 | |||
835 | int 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 | */ | ||
10 | int diva_user_mode_idi_init(void); | ||
11 | void diva_user_mode_idi_finit(void); | ||
12 | void *divas_um_idi_create_entity(dword adapter_nr, void *file); | ||
13 | int divas_um_idi_delete_entity(int adapter_nr, void *entity); | ||
14 | |||
15 | typedef int (*divas_um_idi_copy_to_user_fn_t) (void *os_handle, | ||
16 | void *dst, | ||
17 | const void *src, | ||
18 | int length); | ||
19 | typedef int (*divas_um_idi_copy_from_user_fn_t) (void *os_handle, | ||
20 | void *dst, | ||
21 | const void *src, | ||
22 | int length); | ||
23 | |||
24 | int 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 | |||
29 | int 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 | |||
34 | int diva_user_mode_idi_ind_ready(void *entity, void *os_handle); | ||
35 | void *diva_um_id_get_os_context(void *entity); | ||
36 | int diva_os_get_context_size(void); | ||
37 | int divas_um_idi_entity_assigned(void *entity); | ||
38 | int divas_um_idi_entity_start_remove(void *entity); | ||
39 | |||
40 | void diva_um_idi_start_wdog(void *entity); | ||
41 | void 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 | |||
11 | typedef 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 | */ | ||
32 | typedef 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 | |||
39 | typedef struct _diva_um_idi_ind_parameters { | ||
40 | dword Ind; | ||
41 | dword IndCh; | ||
42 | } diva_um_idi_ind_parameters_t; | ||
43 | |||
44 | typedef struct _diva_um_idi_rc_parameters { | ||
45 | dword Rc; | ||
46 | dword RcCh; | ||
47 | } diva_um_idi_rc_parameters_t; | ||
48 | |||
49 | typedef 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 | */ | ||
62 | typedef 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 | |||
9 | typedef 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 | |||
22 | typedef union _divas_card_resources { | ||
23 | divas_pci_card_resources_t pci; | ||
24 | } divas_card_resources_t; | ||
25 | |||
26 | struct _diva_os_xdi_adapter; | ||
27 | typedef int (*diva_init_card_proc_t) (struct _diva_os_xdi_adapter * a); | ||
28 | typedef int (*diva_cmd_card_proc_t) (struct _diva_os_xdi_adapter * a, | ||
29 | diva_xdi_um_cfg_cmd_t * data, | ||
30 | int length); | ||
31 | typedef 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 | |||
37 | typedef 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 | |||
44 | typedef 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 | |||
49 | typedef 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 | |||
86 | typedef struct _diva_xdi_um_cfg_cmd_data_set_features { | ||
87 | dword features; | ||
88 | } diva_xdi_um_cfg_cmd_data_set_features_t; | ||
89 | |||
90 | typedef struct _diva_xdi_um_cfg_cmd_data_start { | ||
91 | dword offset; | ||
92 | dword features; | ||
93 | } diva_xdi_um_cfg_cmd_data_start_t; | ||
94 | |||
95 | typedef 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 | |||
101 | typedef 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 | |||
106 | typedef 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 | |||
112 | typedef 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 | |||
120 | typedef 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 | */ | ||
26 | static char diva_xdi_common_code_build[] = "102-52"; | ||