Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / isdn / hardware / eicon / maintidi.c
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, "Unknown 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, "Unknown 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                 if (diva_strace_read_uint(pVar, &l2_state))
964                         return -1;
965
966                 switch (l2_state) {
967                 case 0:
968                         strcpy(tmp, "Idle");
969                         break;
970                 case 1:
971                         strcpy(tmp, "Layer2 UP");
972                         break;
973                 case 2:
974                         strcpy(tmp, "Layer2 Disconnecting");
975                         break;
976                 case 3:
977                         strcpy(tmp, "Layer2 Connecting");
978                         break;
979                 case 4:
980                         strcpy(tmp, "SPID Initializing");
981                         break;
982                 case 5:
983                         strcpy(tmp, "SPID Initialised");
984                         break;
985                 case 6:
986                         strcpy(tmp, "Layer2 Connecting");
987                         break;
988
989                 case  7:
990                         strcpy(tmp, "Auto SPID Stopped");
991                         break;
992
993                 case  8:
994                         strcpy(tmp, "Auto SPID Idle");
995                         break;
996
997                 case  9:
998                         strcpy(tmp, "Auto SPID Requested");
999                         break;
1000
1001                 case  10:
1002                         strcpy(tmp, "Auto SPID Delivery");
1003                         break;
1004
1005                 case 11:
1006                         strcpy(tmp, "Auto SPID Complete");
1007                         break;
1008
1009                 default:
1010                         sprintf(tmp, "U:%d", (int)l2_state);
1011                 }
1012                 if (pLib->l2_trace == 1) {
1013                         pLib->l2_trace = 2;
1014                 } else {
1015                         diva_trace_notify_user(pLib, 0, DIVA_SUPER_TRACE_INTERFACE_CHANGE);
1016                 }
1017                 return (0);
1018         }
1019
1020         if (!strncmp("Statistics\\Incoming Calls\\Calls", path, pVar->path_length) ||
1021             !strncmp("Statistics\\Incoming Calls\\Connected", path, pVar->path_length)) {
1022                 return (SuperTraceGetIncomingCallStatistics(pLib));
1023         }
1024
1025         if (!strncmp("Statistics\\Outgoing Calls\\Calls", path, pVar->path_length) ||
1026             !strncmp("Statistics\\Outgoing Calls\\Connected", path, pVar->path_length)) {
1027                 return (SuperTraceGetOutgoingCallStatistics(pLib));
1028         }
1029
1030         return (-1);
1031 }
1032
1033 static int diva_line_event(diva_strace_context_t *pLib, int Channel) {
1034         pLib->pending_line_status |= (1L << (Channel - 1));
1035         return (0);
1036 }
1037
1038 static int diva_modem_event(diva_strace_context_t *pLib, int Channel) {
1039         pLib->pending_modem_status |= (1L << (Channel - 1));
1040         return (0);
1041 }
1042
1043 static int diva_fax_event(diva_strace_context_t *pLib, int Channel) {
1044         pLib->pending_fax_status |= (1L << (Channel - 1));
1045         return (0);
1046 }
1047
1048 /*
1049   Process INFO indications that arrive from the card
1050   Uses path of first I.E. to detect the source of the
1051   infication
1052 */
1053 static int process_idi_info(diva_strace_context_t *pLib,
1054                             diva_man_var_header_t *pVar) {
1055         const char *path = (char *)&pVar->path_length + 1;
1056         char name[64];
1057         int i, len;
1058
1059         /*
1060           First look for Modem Status Info
1061         */
1062         for (i = pLib->Channels; i > 0; i--) {
1063                 len = sprintf(name, "State\\B%d\\Modem", i);
1064                 if (!strncmp(name, path, len)) {
1065                         return (diva_modem_info(pLib, i, pVar));
1066                 }
1067         }
1068
1069         /*
1070           Look for Fax Status Info
1071         */
1072         for (i = pLib->Channels; i > 0; i--) {
1073                 len = sprintf(name, "State\\B%d\\FAX", i);
1074                 if (!strncmp(name, path, len)) {
1075                         return (diva_fax_info(pLib, i, pVar));
1076                 }
1077         }
1078
1079         /*
1080           Look for Line Status Info
1081         */
1082         for (i = pLib->Channels; i > 0; i--) {
1083                 len = sprintf(name, "State\\B%d", i);
1084                 if (!strncmp(name, path, len)) {
1085                         return (diva_line_info(pLib, i, pVar));
1086                 }
1087         }
1088
1089         if (!diva_ifc_statistics(pLib, pVar)) {
1090                 return (0);
1091         }
1092
1093         return (-1);
1094 }
1095
1096 /*
1097   MODEM INSTANCE STATE UPDATE
1098
1099   Update Modem Status Information and issue notification to user,
1100   that will inform about change in the state of modem instance, that is
1101   associuated with this channel
1102 */
1103 static int diva_modem_info(diva_strace_context_t *pLib,
1104                            int Channel,
1105                            diva_man_var_header_t *pVar) {
1106         diva_man_var_header_t *cur;
1107         int i, nr = Channel - 1;
1108
1109         for (i  = pLib->modem_parse_entry_first[nr];
1110              i <= pLib->modem_parse_entry_last[nr]; i++) {
1111                 if ((cur = find_var(pVar, pLib->parse_table[i].path))) {
1112                         if (diva_trace_read_variable(cur, pLib->parse_table[i].variable)) {
1113                                 diva_trace_error(pLib, -3, __FILE__, __LINE__);
1114                                 return (-1);
1115                         }
1116                 } else {
1117                         diva_trace_error(pLib, -2, __FILE__, __LINE__);
1118                         return (-1);
1119                 }
1120         }
1121
1122         /*
1123           We do not use first event to notify user - this is the event that is
1124           generated as result of EVENT ON operation and is used only to initialize
1125           internal variables of application
1126         */
1127         if (pLib->modem_init_event & (1L << nr)) {
1128                 diva_trace_notify_user(pLib, nr, DIVA_SUPER_TRACE_NOTIFY_MODEM_CHANGE);
1129         } else {
1130                 pLib->modem_init_event |= (1L << nr);
1131         }
1132
1133         return (0);
1134 }
1135
1136 static int diva_fax_info(diva_strace_context_t *pLib,
1137                          int Channel,
1138                          diva_man_var_header_t *pVar) {
1139         diva_man_var_header_t *cur;
1140         int i, nr = Channel - 1;
1141
1142         for (i  = pLib->fax_parse_entry_first[nr];
1143              i <= pLib->fax_parse_entry_last[nr]; i++) {
1144                 if ((cur = find_var(pVar, pLib->parse_table[i].path))) {
1145                         if (diva_trace_read_variable(cur, pLib->parse_table[i].variable)) {
1146                                 diva_trace_error(pLib, -3, __FILE__, __LINE__);
1147                                 return (-1);
1148                         }
1149                 } else {
1150                         diva_trace_error(pLib, -2, __FILE__, __LINE__);
1151                         return (-1);
1152                 }
1153         }
1154
1155         /*
1156           We do not use first event to notify user - this is the event that is
1157           generated as result of EVENT ON operation and is used only to initialize
1158           internal variables of application
1159         */
1160         if (pLib->fax_init_event & (1L << nr)) {
1161                 diva_trace_notify_user(pLib, nr, DIVA_SUPER_TRACE_NOTIFY_FAX_CHANGE);
1162         } else {
1163                 pLib->fax_init_event |= (1L << nr);
1164         }
1165
1166         return (0);
1167 }
1168
1169 /*
1170   LINE STATE UPDATE
1171   Update Line Status Information and issue notification to user,
1172   that will inform about change in the line state.
1173 */
1174 static int diva_line_info(diva_strace_context_t *pLib,
1175                           int Channel,
1176                           diva_man_var_header_t *pVar) {
1177         diva_man_var_header_t *cur;
1178         int i, nr = Channel - 1;
1179
1180         for (i = pLib->line_parse_entry_first[nr];
1181              i <= pLib->line_parse_entry_last[nr]; i++) {
1182                 if ((cur = find_var(pVar, pLib->parse_table[i].path))) {
1183                         if (diva_trace_read_variable(cur, pLib->parse_table[i].variable)) {
1184                                 diva_trace_error(pLib, -3, __FILE__, __LINE__);
1185                                 return (-1);
1186                         }
1187                 } else {
1188                         diva_trace_error(pLib, -2 , __FILE__, __LINE__);
1189                         return (-1);
1190                 }
1191         }
1192
1193         /*
1194           We do not use first event to notify user - this is the event that is
1195           generated as result of EVENT ON operation and is used only to initialize
1196           internal variables of application
1197
1198           Exception is is if the line is "online". In this case we have to notify
1199           user about this confition.
1200         */
1201         if (pLib->line_init_event & (1L << nr)) {
1202                 diva_trace_notify_user(pLib, nr, DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE);
1203         } else {
1204                 pLib->line_init_event |= (1L << nr);
1205                 if (strcmp(&pLib->lines[nr].Line[0], "Idle")) {
1206                         diva_trace_notify_user(pLib, nr, DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE);
1207                 }
1208         }
1209
1210         return (0);
1211 }
1212
1213 /*
1214   Move position to next vatianle in the chain
1215 */
1216 static diva_man_var_header_t *get_next_var(diva_man_var_header_t *pVar) {
1217         byte *msg = (byte *)pVar;
1218         byte *start;
1219         int msg_length;
1220
1221         if (*msg != ESC) return NULL;
1222
1223         start = msg + 2;
1224         msg_length = *(msg + 1);
1225         msg = (start + msg_length);
1226
1227         if (*msg != ESC) return NULL;
1228
1229         return ((diva_man_var_header_t *)msg);
1230 }
1231
1232 /*
1233   Move position to variable with given name
1234 */
1235 static diva_man_var_header_t *find_var(diva_man_var_header_t *pVar,
1236                                        const char *name) {
1237         const char *path;
1238
1239         do {
1240                 path = (char *)&pVar->path_length + 1;
1241
1242                 if (!strncmp(name, path, pVar->path_length)) {
1243                         break;
1244                 }
1245         } while ((pVar = get_next_var(pVar)));
1246
1247         return (pVar);
1248 }
1249
1250 static void diva_create_line_parse_table(diva_strace_context_t *pLib,
1251                                          int Channel) {
1252         diva_trace_line_state_t *pLine = &pLib->lines[Channel];
1253         int nr = Channel + 1;
1254
1255         if ((pLib->cur_parse_entry + LINE_PARSE_ENTRIES) >= pLib->parse_entries) {
1256                 diva_trace_error(pLib, -1, __FILE__, __LINE__);
1257                 return;
1258         }
1259
1260         pLine->ChannelNumber = nr;
1261
1262         pLib->line_parse_entry_first[Channel] = pLib->cur_parse_entry;
1263
1264         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1265                 "State\\B%d\\Framing", nr);
1266         pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Framing[0];
1267
1268         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1269                 "State\\B%d\\Line", nr);
1270         pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Line[0];
1271
1272         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1273                 "State\\B%d\\Layer2", nr);
1274         pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Layer2[0];
1275
1276         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1277                 "State\\B%d\\Layer3", nr);
1278         pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Layer3[0];
1279
1280         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1281                 "State\\B%d\\Remote Address", nr);
1282         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1283                 &pLine->RemoteAddress[0];
1284
1285         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1286                 "State\\B%d\\Remote SubAddr", nr);
1287         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1288                 &pLine->RemoteSubAddress[0];
1289
1290         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1291                 "State\\B%d\\Local Address", nr);
1292         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1293                 &pLine->LocalAddress[0];
1294
1295         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1296                 "State\\B%d\\Local SubAddr", nr);
1297         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1298                 &pLine->LocalSubAddress[0];
1299
1300         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1301                 "State\\B%d\\BC", nr);
1302         pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->call_BC;
1303
1304         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1305                 "State\\B%d\\HLC", nr);
1306         pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->call_HLC;
1307
1308         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1309                 "State\\B%d\\LLC", nr);
1310         pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->call_LLC;
1311
1312         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1313                 "State\\B%d\\Charges", nr);
1314         pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Charges;
1315
1316         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1317                 "State\\B%d\\Call Reference", nr);
1318         pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->CallReference;
1319
1320         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1321                 "State\\B%d\\Last Disc Cause", nr);
1322         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1323                 &pLine->LastDisconnecCause;
1324
1325         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1326                 "State\\B%d\\User ID", nr);
1327         pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->UserID[0];
1328
1329         pLib->line_parse_entry_last[Channel] = pLib->cur_parse_entry - 1;
1330 }
1331
1332 static void diva_create_fax_parse_table(diva_strace_context_t *pLib,
1333                                         int Channel) {
1334         diva_trace_fax_state_t *pFax = &pLib->lines[Channel].fax;
1335         int nr = Channel + 1;
1336
1337         if ((pLib->cur_parse_entry + FAX_PARSE_ENTRIES) >= pLib->parse_entries) {
1338                 diva_trace_error(pLib, -1, __FILE__, __LINE__);
1339                 return;
1340         }
1341         pFax->ChannelNumber = nr;
1342
1343         pLib->fax_parse_entry_first[Channel] = pLib->cur_parse_entry;
1344
1345         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1346                 "State\\B%d\\FAX\\Event", nr);
1347         pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Event;
1348
1349         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1350                 "State\\B%d\\FAX\\Page Counter", nr);
1351         pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Page_Counter;
1352
1353         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1354                 "State\\B%d\\FAX\\Features", nr);
1355         pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Features;
1356
1357         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1358                 "State\\B%d\\FAX\\Station ID", nr);
1359         pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Station_ID[0];
1360
1361         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1362                 "State\\B%d\\FAX\\Subaddress", nr);
1363         pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Subaddress[0];
1364
1365         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1366                 "State\\B%d\\FAX\\Password", nr);
1367         pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Password[0];
1368
1369         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1370                 "State\\B%d\\FAX\\Speed", nr);
1371         pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Speed;
1372
1373         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1374                 "State\\B%d\\FAX\\Resolution", nr);
1375         pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Resolution;
1376
1377         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1378                 "State\\B%d\\FAX\\Paper Width", nr);
1379         pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Paper_Width;
1380
1381         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1382                 "State\\B%d\\FAX\\Paper Length", nr);
1383         pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Paper_Length;
1384
1385         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1386                 "State\\B%d\\FAX\\Scanline Time", nr);
1387         pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Scanline_Time;
1388
1389         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1390                 "State\\B%d\\FAX\\Disc Reason", nr);
1391         pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Disc_Reason;
1392
1393         pLib->fax_parse_entry_last[Channel] = pLib->cur_parse_entry - 1;
1394 }
1395
1396 static void diva_create_modem_parse_table(diva_strace_context_t *pLib,
1397                                           int Channel) {
1398         diva_trace_modem_state_t *pModem = &pLib->lines[Channel].modem;
1399         int nr = Channel + 1;
1400
1401         if ((pLib->cur_parse_entry + MODEM_PARSE_ENTRIES) >= pLib->parse_entries) {
1402                 diva_trace_error(pLib, -1, __FILE__, __LINE__);
1403                 return;
1404         }
1405         pModem->ChannelNumber = nr;
1406
1407         pLib->modem_parse_entry_first[Channel] = pLib->cur_parse_entry;
1408
1409         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1410                 "State\\B%d\\Modem\\Event", nr);
1411         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->Event;
1412
1413         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1414                 "State\\B%d\\Modem\\Norm", nr);
1415         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->Norm;
1416
1417         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1418                 "State\\B%d\\Modem\\Options", nr);
1419         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->Options;
1420
1421         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1422                 "State\\B%d\\Modem\\TX Speed", nr);
1423         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->TxSpeed;
1424
1425         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1426                 "State\\B%d\\Modem\\RX Speed", nr);
1427         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RxSpeed;
1428
1429         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1430                 "State\\B%d\\Modem\\Roundtrip ms", nr);
1431         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RoundtripMsec;
1432
1433         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1434                 "State\\B%d\\Modem\\Symbol Rate", nr);
1435         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->SymbolRate;
1436
1437         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1438                 "State\\B%d\\Modem\\RX Level dBm", nr);
1439         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RxLeveldBm;
1440
1441         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1442                 "State\\B%d\\Modem\\Echo Level dBm", nr);
1443         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->EchoLeveldBm;
1444
1445         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1446                 "State\\B%d\\Modem\\SNR dB", nr);
1447         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->SNRdb;
1448
1449         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1450                 "State\\B%d\\Modem\\MAE", nr);
1451         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->MAE;
1452
1453         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1454                 "State\\B%d\\Modem\\Local Retrains", nr);
1455         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->LocalRetrains;
1456
1457         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1458                 "State\\B%d\\Modem\\Remote Retrains", nr);
1459         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RemoteRetrains;
1460
1461         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1462                 "State\\B%d\\Modem\\Local Resyncs", nr);
1463         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->LocalResyncs;
1464
1465         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1466                 "State\\B%d\\Modem\\Remote Resyncs", nr);
1467         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RemoteResyncs;
1468
1469         sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1470                 "State\\B%d\\Modem\\Disc Reason", nr);
1471         pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->DiscReason;
1472
1473         pLib->modem_parse_entry_last[Channel] = pLib->cur_parse_entry - 1;
1474 }
1475
1476 static void diva_create_parse_table(diva_strace_context_t *pLib) {
1477         int i;
1478
1479         for (i = 0; i < pLib->Channels; i++) {
1480                 diva_create_line_parse_table(pLib, i);
1481                 diva_create_modem_parse_table(pLib, i);
1482                 diva_create_fax_parse_table(pLib, i);
1483         }
1484
1485         pLib->statistic_parse_first = pLib->cur_parse_entry;
1486
1487         /*
1488           Outgoing Calls
1489         */
1490         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1491                "Statistics\\Outgoing Calls\\Calls");
1492         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1493                 &pLib->InterfaceStat.outg.Calls;
1494
1495         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1496                "Statistics\\Outgoing Calls\\Connected");
1497         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1498                 &pLib->InterfaceStat.outg.Connected;
1499
1500         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1501                "Statistics\\Outgoing Calls\\User Busy");
1502         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1503                 &pLib->InterfaceStat.outg.User_Busy;
1504
1505         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1506                "Statistics\\Outgoing Calls\\No Answer");
1507         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1508                 &pLib->InterfaceStat.outg.No_Answer;
1509
1510         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1511                "Statistics\\Outgoing Calls\\Wrong Number");
1512         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1513                 &pLib->InterfaceStat.outg.Wrong_Number;
1514
1515         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1516                "Statistics\\Outgoing Calls\\Call Rejected");
1517         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1518                 &pLib->InterfaceStat.outg.Call_Rejected;
1519
1520         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1521                "Statistics\\Outgoing Calls\\Other Failures");
1522         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1523                 &pLib->InterfaceStat.outg.Other_Failures;
1524
1525         /*
1526           Incoming Calls
1527         */
1528         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1529                "Statistics\\Incoming Calls\\Calls");
1530         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1531                 &pLib->InterfaceStat.inc.Calls;
1532
1533         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1534                "Statistics\\Incoming Calls\\Connected");
1535         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1536                 &pLib->InterfaceStat.inc.Connected;
1537
1538         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1539                "Statistics\\Incoming Calls\\User Busy");
1540         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1541                 &pLib->InterfaceStat.inc.User_Busy;
1542
1543         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1544                "Statistics\\Incoming Calls\\Call Rejected");
1545         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1546                 &pLib->InterfaceStat.inc.Call_Rejected;
1547
1548         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1549                "Statistics\\Incoming Calls\\Wrong Number");
1550         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1551                 &pLib->InterfaceStat.inc.Wrong_Number;
1552
1553         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1554                "Statistics\\Incoming Calls\\Incompatible Dst");
1555         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1556                 &pLib->InterfaceStat.inc.Incompatible_Dst;
1557
1558         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1559                "Statistics\\Incoming Calls\\Out of Order");
1560         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1561                 &pLib->InterfaceStat.inc.Out_of_Order;
1562
1563         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1564                "Statistics\\Incoming Calls\\Ignored");
1565         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1566                 &pLib->InterfaceStat.inc.Ignored;
1567
1568         /*
1569           Modem Statistics
1570         */
1571         pLib->mdm_statistic_parse_first = pLib->cur_parse_entry;
1572
1573         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1574                "Statistics\\Modem\\Disc Normal");
1575         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1576                 &pLib->InterfaceStat.mdm.Disc_Normal;
1577
1578         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1579                "Statistics\\Modem\\Disc Unspecified");
1580         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1581                 &pLib->InterfaceStat.mdm.Disc_Unspecified;
1582
1583         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1584                "Statistics\\Modem\\Disc Busy Tone");
1585         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1586                 &pLib->InterfaceStat.mdm.Disc_Busy_Tone;
1587
1588         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1589                "Statistics\\Modem\\Disc Congestion");
1590         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1591                 &pLib->InterfaceStat.mdm.Disc_Congestion;
1592
1593         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1594                "Statistics\\Modem\\Disc Carr. Wait");
1595         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1596                 &pLib->InterfaceStat.mdm.Disc_Carr_Wait;
1597
1598         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1599                "Statistics\\Modem\\Disc Trn Timeout");
1600         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1601                 &pLib->InterfaceStat.mdm.Disc_Trn_Timeout;
1602
1603         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1604                "Statistics\\Modem\\Disc Incompat.");
1605         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1606                 &pLib->InterfaceStat.mdm.Disc_Incompat;
1607
1608         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1609                "Statistics\\Modem\\Disc Frame Rej.");
1610         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1611                 &pLib->InterfaceStat.mdm.Disc_Frame_Rej;
1612
1613         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1614                "Statistics\\Modem\\Disc V42bis");
1615         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1616                 &pLib->InterfaceStat.mdm.Disc_V42bis;
1617
1618         pLib->mdm_statistic_parse_last  = pLib->cur_parse_entry - 1;
1619
1620         /*
1621           Fax Statistics
1622         */
1623         pLib->fax_statistic_parse_first = pLib->cur_parse_entry;
1624
1625         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1626                "Statistics\\FAX\\Disc Normal");
1627         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1628                 &pLib->InterfaceStat.fax.Disc_Normal;
1629
1630         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1631                "Statistics\\FAX\\Disc Not Ident.");
1632         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1633                 &pLib->InterfaceStat.fax.Disc_Not_Ident;
1634
1635         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1636                "Statistics\\FAX\\Disc No Response");
1637         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1638                 &pLib->InterfaceStat.fax.Disc_No_Response;
1639
1640         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1641                "Statistics\\FAX\\Disc Retries");
1642         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1643                 &pLib->InterfaceStat.fax.Disc_Retries;
1644
1645         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1646                "Statistics\\FAX\\Disc Unexp. Msg.");
1647         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1648                 &pLib->InterfaceStat.fax.Disc_Unexp_Msg;
1649
1650         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1651                "Statistics\\FAX\\Disc No Polling.");
1652         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1653                 &pLib->InterfaceStat.fax.Disc_No_Polling;
1654
1655         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1656                "Statistics\\FAX\\Disc Training");
1657         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1658                 &pLib->InterfaceStat.fax.Disc_Training;
1659
1660         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1661                "Statistics\\FAX\\Disc Unexpected");
1662         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1663                 &pLib->InterfaceStat.fax.Disc_Unexpected;
1664
1665         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1666                "Statistics\\FAX\\Disc Application");
1667         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1668                 &pLib->InterfaceStat.fax.Disc_Application;
1669
1670         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1671                "Statistics\\FAX\\Disc Incompat.");
1672         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1673                 &pLib->InterfaceStat.fax.Disc_Incompat;
1674
1675         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1676                "Statistics\\FAX\\Disc No Command");
1677         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1678                 &pLib->InterfaceStat.fax.Disc_No_Command;
1679
1680         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1681                "Statistics\\FAX\\Disc Long Msg");
1682         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1683                 &pLib->InterfaceStat.fax.Disc_Long_Msg;
1684
1685         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1686                "Statistics\\FAX\\Disc Supervisor");
1687         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1688                 &pLib->InterfaceStat.fax.Disc_Supervisor;
1689
1690         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1691                "Statistics\\FAX\\Disc SUB SEP PWD");
1692         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1693                 &pLib->InterfaceStat.fax.Disc_SUB_SEP_PWD;
1694
1695         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1696                "Statistics\\FAX\\Disc Invalid Msg");
1697         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1698                 &pLib->InterfaceStat.fax.Disc_Invalid_Msg;
1699
1700         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1701                "Statistics\\FAX\\Disc Page Coding");
1702         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1703                 &pLib->InterfaceStat.fax.Disc_Page_Coding;
1704
1705         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1706                "Statistics\\FAX\\Disc App Timeout");
1707         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1708                 &pLib->InterfaceStat.fax.Disc_App_Timeout;
1709
1710         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1711                "Statistics\\FAX\\Disc Unspecified");
1712         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1713                 &pLib->InterfaceStat.fax.Disc_Unspecified;
1714
1715         pLib->fax_statistic_parse_last  = pLib->cur_parse_entry - 1;
1716
1717         /*
1718           B-Layer1"
1719         */
1720         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1721                "Statistics\\B-Layer1\\X-Frames");
1722         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1723                 &pLib->InterfaceStat.b1.X_Frames;
1724
1725         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1726                "Statistics\\B-Layer1\\X-Bytes");
1727         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1728                 &pLib->InterfaceStat.b1.X_Bytes;
1729
1730         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1731                "Statistics\\B-Layer1\\X-Errors");
1732         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1733                 &pLib->InterfaceStat.b1.X_Errors;
1734
1735         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1736                "Statistics\\B-Layer1\\R-Frames");
1737         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1738                 &pLib->InterfaceStat.b1.R_Frames;
1739
1740         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1741                "Statistics\\B-Layer1\\R-Bytes");
1742         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1743                 &pLib->InterfaceStat.b1.R_Bytes;
1744
1745         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1746                "Statistics\\B-Layer1\\R-Errors");
1747         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1748                 &pLib->InterfaceStat.b1.R_Errors;
1749
1750         /*
1751           B-Layer2
1752         */
1753         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1754                "Statistics\\B-Layer2\\X-Frames");
1755         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1756                 &pLib->InterfaceStat.b2.X_Frames;
1757
1758         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1759                "Statistics\\B-Layer2\\X-Bytes");
1760         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1761                 &pLib->InterfaceStat.b2.X_Bytes;
1762
1763         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1764                "Statistics\\B-Layer2\\X-Errors");
1765         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1766                 &pLib->InterfaceStat.b2.X_Errors;
1767
1768         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1769                "Statistics\\B-Layer2\\R-Frames");
1770         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1771                 &pLib->InterfaceStat.b2.R_Frames;
1772
1773         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1774                "Statistics\\B-Layer2\\R-Bytes");
1775         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1776                 &pLib->InterfaceStat.b2.R_Bytes;
1777
1778         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1779                "Statistics\\B-Layer2\\R-Errors");
1780         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1781                 &pLib->InterfaceStat.b2.R_Errors;
1782
1783         /*
1784           D-Layer1
1785         */
1786         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1787                "Statistics\\D-Layer1\\X-Frames");
1788         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1789                 &pLib->InterfaceStat.d1.X_Frames;
1790
1791         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1792                "Statistics\\D-Layer1\\X-Bytes");
1793         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1794                 &pLib->InterfaceStat.d1.X_Bytes;
1795
1796         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1797                "Statistics\\D-Layer1\\X-Errors");
1798         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1799                 &pLib->InterfaceStat.d1.X_Errors;
1800
1801         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1802                "Statistics\\D-Layer1\\R-Frames");
1803         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1804                 &pLib->InterfaceStat.d1.R_Frames;
1805
1806         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1807                "Statistics\\D-Layer1\\R-Bytes");
1808         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1809                 &pLib->InterfaceStat.d1.R_Bytes;
1810
1811         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1812                "Statistics\\D-Layer1\\R-Errors");
1813         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1814                 &pLib->InterfaceStat.d1.R_Errors;
1815
1816         /*
1817           D-Layer2
1818         */
1819         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1820                "Statistics\\D-Layer2\\X-Frames");
1821         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1822                 &pLib->InterfaceStat.d2.X_Frames;
1823
1824         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1825                "Statistics\\D-Layer2\\X-Bytes");
1826         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1827                 &pLib->InterfaceStat.d2.X_Bytes;
1828
1829         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1830                "Statistics\\D-Layer2\\X-Errors");
1831         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1832                 &pLib->InterfaceStat.d2.X_Errors;
1833
1834         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1835                "Statistics\\D-Layer2\\R-Frames");
1836         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1837                 &pLib->InterfaceStat.d2.R_Frames;
1838
1839         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1840                "Statistics\\D-Layer2\\R-Bytes");
1841         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1842                 &pLib->InterfaceStat.d2.R_Bytes;
1843
1844         strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1845                "Statistics\\D-Layer2\\R-Errors");
1846         pLib->parse_table[pLib->cur_parse_entry++].variable = \
1847                 &pLib->InterfaceStat.d2.R_Errors;
1848
1849
1850         pLib->statistic_parse_last  = pLib->cur_parse_entry - 1;
1851 }
1852
1853 static void diva_trace_error(diva_strace_context_t *pLib,
1854                              int error, const char *file, int line) {
1855         if (pLib->user_proc_table.error_notify_proc) {
1856                 (*(pLib->user_proc_table.error_notify_proc))(\
1857                         pLib->user_proc_table.user_context,
1858                         &pLib->instance, pLib->Adapter,
1859                         error, file, line);
1860         }
1861 }
1862
1863 /*
1864   Delivery notification to user
1865 */
1866 static void diva_trace_notify_user(diva_strace_context_t *pLib,
1867                                    int Channel,
1868                                    int notify_subject) {
1869         if (pLib->user_proc_table.notify_proc) {
1870                 (*(pLib->user_proc_table.notify_proc))(pLib->user_proc_table.user_context,
1871                                                        &pLib->instance,
1872                                                        pLib->Adapter,
1873                                                        &pLib->lines[Channel],
1874                                                        notify_subject);
1875         }
1876 }
1877
1878 /*
1879   Read variable value to they destination based on the variable type
1880 */
1881 static int diva_trace_read_variable(diva_man_var_header_t *pVar,
1882                                     void *variable) {
1883         switch (pVar->type) {
1884         case 0x03: /* MI_ASCIIZ - syting                               */
1885                 return (diva_strace_read_asz(pVar, (char *)variable));
1886         case 0x04: /* MI_ASCII  - string                               */
1887                 return (diva_strace_read_asc(pVar, (char *)variable));
1888         case 0x05: /* MI_NUMBER - counted sequence of bytes            */
1889                 return (diva_strace_read_ie(pVar, (diva_trace_ie_t *)variable));
1890         case 0x81: /* MI_INT    - signed integer                       */
1891                 return (diva_strace_read_int(pVar, (int *)variable));
1892         case 0x82: /* MI_UINT   - unsigned integer                     */
1893                 return (diva_strace_read_uint(pVar, (dword *)variable));
1894         case 0x83: /* MI_HINT   - unsigned integer, hex representetion */
1895                 return (diva_strace_read_uint(pVar, (dword *)variable));
1896         case 0x87: /* MI_BITFLD - unsigned integer, bit representation */
1897                 return (diva_strace_read_uint(pVar, (dword *)variable));
1898         }
1899
1900         /*
1901           This type of variable is not handled, indicate error
1902           Or one problem in management interface, or in application recodeing
1903           table, or this application should handle it.
1904         */
1905         return (-1);
1906 }
1907
1908 /*
1909   Read signed integer to destination
1910 */
1911 static int diva_strace_read_int(diva_man_var_header_t *pVar, int *var) {
1912         byte *ptr = (char *)&pVar->path_length;
1913         int value;
1914
1915         ptr += (pVar->path_length + 1);
1916
1917         switch (pVar->value_length) {
1918         case 1:
1919                 value = *(char *)ptr;
1920                 break;
1921
1922         case 2:
1923                 value = (short)GET_WORD(ptr);
1924                 break;
1925
1926         case 4:
1927                 value = (int)GET_DWORD(ptr);
1928                 break;
1929
1930         default:
1931                 return (-1);
1932         }
1933
1934         *var = value;
1935
1936         return (0);
1937 }
1938
1939 static int diva_strace_read_uint(diva_man_var_header_t *pVar, dword *var) {
1940         byte *ptr = (char *)&pVar->path_length;
1941         dword value;
1942
1943         ptr += (pVar->path_length + 1);
1944
1945         switch (pVar->value_length) {
1946         case 1:
1947                 value = (byte)(*ptr);
1948                 break;
1949
1950         case 2:
1951                 value = (word)GET_WORD(ptr);
1952                 break;
1953
1954         case 3:
1955                 value  = (dword)GET_DWORD(ptr);
1956                 value &= 0x00ffffff;
1957                 break;
1958
1959         case 4:
1960                 value = (dword)GET_DWORD(ptr);
1961                 break;
1962
1963         default:
1964                 return (-1);
1965         }
1966
1967         *var = value;
1968
1969         return (0);
1970 }
1971
1972 /*
1973   Read zero terminated ASCII string
1974 */
1975 static int diva_strace_read_asz(diva_man_var_header_t *pVar, char *var) {
1976         char *ptr = (char *)&pVar->path_length;
1977         int length;
1978
1979         ptr += (pVar->path_length + 1);
1980
1981         if (!(length = pVar->value_length)) {
1982                 length = strlen(ptr);
1983         }
1984         memcpy(var, ptr, length);
1985         var[length] = 0;
1986
1987         return (0);
1988 }
1989
1990 /*
1991   Read counted (with leading length byte) ASCII string
1992 */
1993 static int diva_strace_read_asc(diva_man_var_header_t *pVar, char *var) {
1994         char *ptr = (char *)&pVar->path_length;
1995
1996         ptr += (pVar->path_length + 1);
1997         memcpy(var, ptr + 1, *ptr);
1998         var[(int)*ptr] = 0;
1999
2000         return (0);
2001 }
2002
2003 /*
2004   Read one information element - i.e. one string of byte values with
2005   one length byte in front
2006 */
2007 static int diva_strace_read_ie(diva_man_var_header_t *pVar,
2008                                diva_trace_ie_t *var) {
2009         char *ptr = (char *)&pVar->path_length;
2010
2011         ptr += (pVar->path_length + 1);
2012
2013         var->length = *ptr;
2014         memcpy(&var->data[0], ptr + 1, *ptr);
2015
2016         return (0);
2017 }
2018
2019 static int SuperTraceSetAudioTap(void *hLib, int Channel, int on) {
2020         diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2021
2022         if ((Channel < 1) || (Channel > pLib->Channels)) {
2023                 return (-1);
2024         }
2025         Channel--;
2026
2027         if (on) {
2028                 pLib->audio_tap_mask |=  (1L << Channel);
2029         } else {
2030                 pLib->audio_tap_mask &= ~(1L << Channel);
2031         }
2032
2033         /*
2034           EYE patterns have TM_M_DATA set as additional
2035           condition
2036         */
2037         if (pLib->audio_tap_mask) {
2038                 pLib->trace_event_mask |= TM_M_DATA;
2039         } else {
2040                 pLib->trace_event_mask &= ~TM_M_DATA;
2041         }
2042
2043         return (ScheduleNextTraceRequest(pLib));
2044 }
2045
2046 static int SuperTraceSetBChannel(void *hLib, int Channel, int on) {
2047         diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2048
2049         if ((Channel < 1) || (Channel > pLib->Channels)) {
2050                 return (-1);
2051         }
2052         Channel--;
2053
2054         if (on) {
2055                 pLib->bchannel_trace_mask |=  (1L << Channel);
2056         } else {
2057                 pLib->bchannel_trace_mask &= ~(1L << Channel);
2058         }
2059
2060         return (ScheduleNextTraceRequest(pLib));
2061 }
2062
2063 static int SuperTraceSetDChannel(void *hLib, int on) {
2064         diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2065
2066         if (on) {
2067                 pLib->trace_event_mask |= (TM_D_CHAN | TM_C_COMM | TM_DL_ERR | TM_LAYER1);
2068         } else {
2069                 pLib->trace_event_mask &= ~(TM_D_CHAN | TM_C_COMM | TM_DL_ERR | TM_LAYER1);
2070         }
2071
2072         return (ScheduleNextTraceRequest(pLib));
2073 }
2074
2075 static int SuperTraceSetInfo(void *hLib, int on) {
2076         diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2077
2078         if (on) {
2079                 pLib->trace_event_mask |= TM_STRING;
2080         } else {
2081                 pLib->trace_event_mask &= ~TM_STRING;
2082         }
2083
2084         return (ScheduleNextTraceRequest(pLib));
2085 }
2086
2087 static int SuperTraceClearCall(void *hLib, int Channel) {
2088         diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2089
2090         if ((Channel < 1) || (Channel > pLib->Channels)) {
2091                 return (-1);
2092         }
2093         Channel--;
2094
2095         pLib->clear_call_command |= (1L << Channel);
2096
2097         return (ScheduleNextTraceRequest(pLib));
2098 }
2099
2100 /*
2101   Parse and update cumulative statistice
2102 */
2103 static int diva_ifc_statistics(diva_strace_context_t *pLib,
2104                                diva_man_var_header_t *pVar) {
2105         diva_man_var_header_t *cur;
2106         int i, one_updated = 0, mdm_updated = 0, fax_updated = 0;
2107
2108         for (i  = pLib->statistic_parse_first; i <= pLib->statistic_parse_last; i++) {
2109                 if ((cur = find_var(pVar, pLib->parse_table[i].path))) {
2110                         if (diva_trace_read_variable(cur, pLib->parse_table[i].variable)) {
2111                                 diva_trace_error(pLib, -3 , __FILE__, __LINE__);
2112                                 return (-1);
2113                         }
2114                         one_updated = 1;
2115                         if ((i >= pLib->mdm_statistic_parse_first) && (i <= pLib->mdm_statistic_parse_last)) {
2116                                 mdm_updated = 1;
2117                         }
2118                         if ((i >= pLib->fax_statistic_parse_first) && (i <= pLib->fax_statistic_parse_last)) {
2119                                 fax_updated = 1;
2120                         }
2121                 }
2122         }
2123
2124         /*
2125           We do not use first event to notify user - this is the event that is
2126           generated as result of EVENT ON operation and is used only to initialize
2127           internal variables of application
2128         */
2129         if (mdm_updated) {
2130                 diva_trace_notify_user(pLib, 0, DIVA_SUPER_TRACE_NOTIFY_MDM_STAT_CHANGE);
2131         } else if (fax_updated) {
2132                 diva_trace_notify_user(pLib, 0, DIVA_SUPER_TRACE_NOTIFY_FAX_STAT_CHANGE);
2133         } else if (one_updated) {
2134                 diva_trace_notify_user(pLib, 0, DIVA_SUPER_TRACE_NOTIFY_STAT_CHANGE);
2135         }
2136
2137         return (one_updated ? 0 : -1);
2138 }
2139
2140 static int SuperTraceGetOutgoingCallStatistics(void *hLib) {
2141         diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2142         pLib->outgoing_ifc_stats = 1;
2143         return (ScheduleNextTraceRequest(pLib));
2144 }
2145
2146 static int SuperTraceGetIncomingCallStatistics(void *hLib) {
2147         diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2148         pLib->incoming_ifc_stats = 1;
2149         return (ScheduleNextTraceRequest(pLib));
2150 }
2151
2152 static int SuperTraceGetModemStatistics(void *hLib) {
2153         diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2154         pLib->modem_ifc_stats = 1;
2155         return (ScheduleNextTraceRequest(pLib));
2156 }
2157
2158 static int SuperTraceGetFaxStatistics(void *hLib) {
2159         diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2160         pLib->fax_ifc_stats = 1;
2161         return (ScheduleNextTraceRequest(pLib));
2162 }
2163
2164 static int SuperTraceGetBLayer1Statistics(void *hLib) {
2165         diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2166         pLib->b1_ifc_stats = 1;
2167         return (ScheduleNextTraceRequest(pLib));
2168 }
2169
2170 static int SuperTraceGetBLayer2Statistics(void *hLib) {
2171         diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2172         pLib->b2_ifc_stats = 1;
2173         return (ScheduleNextTraceRequest(pLib));
2174 }
2175
2176 static int SuperTraceGetDLayer1Statistics(void *hLib) {
2177         diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2178         pLib->d1_ifc_stats = 1;
2179         return (ScheduleNextTraceRequest(pLib));
2180 }
2181
2182 static int SuperTraceGetDLayer2Statistics(void *hLib) {
2183         diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2184         pLib->d2_ifc_stats = 1;
2185         return (ScheduleNextTraceRequest(pLib));
2186 }
2187
2188 dword DivaSTraceGetMemotyRequirement(int channels) {
2189         dword parse_entries = (MODEM_PARSE_ENTRIES + FAX_PARSE_ENTRIES + \
2190                                STAT_PARSE_ENTRIES + \
2191                                LINE_PARSE_ENTRIES + 1) * channels;
2192         return (sizeof(diva_strace_context_t) + \
2193                 (parse_entries * sizeof(diva_strace_path2action_t)));
2194 }