Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / isdn / hardware / eicon / di.c
1
2 /*
3  *
4  Copyright (c) Eicon Networks, 2002.
5  *
6  This source file is supplied for the use with
7  Eicon Networks range of DIVA Server Adapters.
8  *
9  Eicon File Revision :    2.1
10  *
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation; either version 2, or (at your option)
14  any later version.
15  *
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  See the GNU General Public License for more details.
20  *
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  */
26 #include "platform.h"
27 #include "pc.h"
28 #include "pr_pc.h"
29 #include "di_defs.h"
30 #include "di.h"
31 #if !defined USE_EXTENDED_DEBUGS
32 #include "dimaint.h"
33 #else
34 #define dprintf
35 #endif
36 #include "io.h"
37 #include "dfifo.h"
38 #define PR_RAM  ((struct pr_ram *)0)
39 #define RAM ((struct dual *)0)
40 /*------------------------------------------------------------------*/
41 /* local function prototypes                                        */
42 /*------------------------------------------------------------------*/
43 void pr_out(ADAPTER *a);
44 byte pr_dpc(ADAPTER *a);
45 static byte pr_ready(ADAPTER *a);
46 static byte isdn_rc(ADAPTER *, byte, byte, byte, word, dword, dword);
47 static byte isdn_ind(ADAPTER *, byte, byte, byte, PBUFFER *, byte, word);
48 /* -----------------------------------------------------------------
49    Functions used for the extended XDI Debug
50    macros
51    global convergence counter (used by all adapters)
52    Look by the implementation part of the functions
53    about the parameters.
54    If you change the dubugging parameters, then you should update
55    the aididbg.doc in the IDI doc's.
56    ----------------------------------------------------------------- */
57 #if defined(XDI_USE_XLOG)
58 #define XDI_A_NR(_x_) ((byte)(((ISDN_ADAPTER *)(_x_->io))->ANum))
59 static void xdi_xlog(byte *msg, word code, int length);
60 static byte xdi_xlog_sec = 0;
61 #else
62 #define XDI_A_NR(_x_) ((byte)0)
63 #endif
64 static void xdi_xlog_rc_event(byte Adapter,
65                               byte Id, byte Ch, byte Rc, byte cb, byte type);
66 static void xdi_xlog_request(byte Adapter, byte Id,
67                              byte Ch, byte Req, byte type);
68 static void xdi_xlog_ind(byte Adapter,
69                          byte Id,
70                          byte Ch,
71                          byte Ind,
72                          byte rnr_valid,
73                          byte rnr,
74                          byte type);
75 /*------------------------------------------------------------------*/
76 /* output function                                                  */
77 /*------------------------------------------------------------------*/
78 void pr_out(ADAPTER *a)
79 {
80         byte e_no;
81         ENTITY *this = NULL;
82         BUFFERS *X;
83         word length;
84         word i;
85         word clength;
86         REQ *ReqOut;
87         byte more;
88         byte ReadyCount;
89         byte ReqCount;
90         byte Id;
91         dtrc(dprintf("pr_out"));
92         /* while a request is pending ...                           */
93         e_no = look_req(a);
94         if (!e_no)
95         {
96                 dtrc(dprintf("no_req"));
97                 return;
98         }
99         ReadyCount = pr_ready(a);
100         if (!ReadyCount)
101         {
102                 dtrc(dprintf("not_ready"));
103                 return;
104         }
105         ReqCount = 0;
106         while (e_no && ReadyCount) {
107                 next_req(a);
108                 this = entity_ptr(a, e_no);
109 #ifdef USE_EXTENDED_DEBUGS
110                 if (!this)
111                 {
112                         DBG_FTL(("XDI: [%02x] !A%d ==> NULL entity ptr - try to ignore",
113                                  xdi_xlog_sec++, (int)((ISDN_ADAPTER *)a->io)->ANum))
114                                 e_no = look_req(a);
115                         ReadyCount--;
116                         continue;
117                 }
118                 {
119                         DBG_TRC((">A%d Id=0x%x Req=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, this->Id, this->Req))
120                                 }
121 #else
122                 dbug(dprintf("out:Req=%x,Id=%x,Ch=%x", this->Req, this->Id, this->ReqCh));
123 #endif
124                 /* get address of next available request buffer             */
125                 ReqOut = (REQ *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextReq)];
126 #if defined(DIVA_ISTREAM)
127                 if (!(a->tx_stream[this->Id]   &&
128                       this->Req == N_DATA)) {
129 #endif
130                         /* now copy the data from the current data buffer into the  */
131                         /* adapters request buffer                                  */
132                         length = 0;
133                         i = this->XCurrent;
134                         X = PTR_X(a, this);
135                         while (i < this->XNum && length < 270) {
136                                 clength = min((word)(270 - length), (word)(X[i].PLength-this->XOffset));
137                                 a->ram_out_buffer(a,
138                                                   &ReqOut->XBuffer.P[length],
139                                                   PTR_P(a, this, &X[i].P[this->XOffset]),
140                                                   clength);
141                                 length += clength;
142                                 this->XOffset += clength;
143                                 if (this->XOffset == X[i].PLength) {
144                                         this->XCurrent = (byte)++i;
145                                         this->XOffset = 0;
146                                 }
147                         }
148 #if defined(DIVA_ISTREAM)
149                 } else { /* Use CMA extension in order to transfer data to the card */
150                         i = this->XCurrent;
151                         X = PTR_X(a, this);
152                         while (i < this->XNum) {
153                                 diva_istream_write(a,
154                                                    this->Id,
155                                                    PTR_P(a, this, &X[i].P[0]),
156                                                    X[i].PLength,
157                                                    ((i + 1) == this->XNum),
158                                                    0, 0);
159                                 this->XCurrent = (byte)++i;
160                         }
161                         length = 0;
162                 }
163 #endif
164                 a->ram_outw(a, &ReqOut->XBuffer.length, length);
165                 a->ram_out(a, &ReqOut->ReqId, this->Id);
166                 a->ram_out(a, &ReqOut->ReqCh, this->ReqCh);
167                 /* if it's a specific request (no ASSIGN) ...                */
168                 if (this->Id & 0x1f) {
169                         /* if buffers are left in the list of data buffers do       */
170                         /* do chaining (LL_MDATA, N_MDATA)                          */
171                         this->More++;
172                         if (i < this->XNum && this->MInd) {
173                                 xdi_xlog_request(XDI_A_NR(a), this->Id, this->ReqCh, this->MInd,
174                                                  a->IdTypeTable[this->No]);
175                                 a->ram_out(a, &ReqOut->Req, this->MInd);
176                                 more = true;
177                         }
178                         else {
179                                 xdi_xlog_request(XDI_A_NR(a), this->Id, this->ReqCh, this->Req,
180                                                  a->IdTypeTable[this->No]);
181                                 this->More |= XMOREF;
182                                 a->ram_out(a, &ReqOut->Req, this->Req);
183                                 more = false;
184                                 if (a->FlowControlIdTable[this->ReqCh] == this->Id)
185                                         a->FlowControlSkipTable[this->ReqCh] = true;
186                                 /*
187                                   Note that remove request was sent to the card
188                                 */
189                                 if (this->Req == REMOVE) {
190                                         a->misc_flags_table[e_no] |= DIVA_MISC_FLAGS_REMOVE_PENDING;
191                                 }
192                         }
193                         /* if we did chaining, this entity is put back into the     */
194                         /* request queue                                            */
195                         if (more) {
196                                 req_queue(a, this->No);
197                         }
198                 }
199                 /* else it's a ASSIGN                                       */
200                 else {
201                         /* save the request code used for buffer chaining           */
202                         this->MInd = 0;
203                         if (this->Id == BLLC_ID) this->MInd = LL_MDATA;
204                         if (this->Id == NL_ID ||
205                             this->Id == TASK_ID ||
206                             this->Id == MAN_ID
207                                 ) this->MInd = N_MDATA;
208                         /* send the ASSIGN                                          */
209                         a->IdTypeTable[this->No] = this->Id;
210                         xdi_xlog_request(XDI_A_NR(a), this->Id, this->ReqCh, this->Req, this->Id);
211                         this->More |= XMOREF;
212                         a->ram_out(a, &ReqOut->Req, this->Req);
213                         /* save the reference of the ASSIGN                         */
214                         assign_queue(a, this->No, a->ram_inw(a, &ReqOut->Reference));
215                 }
216                 a->ram_outw(a, &PR_RAM->NextReq, a->ram_inw(a, &ReqOut->next));
217                 ReadyCount--;
218                 ReqCount++;
219                 e_no = look_req(a);
220         }
221         /* send the filled request buffers to the ISDN adapter      */
222         a->ram_out(a, &PR_RAM->ReqInput,
223                    (byte)(a->ram_in(a, &PR_RAM->ReqInput) + ReqCount));
224         /* if it is a 'unreturncoded' UREMOVE request, remove the  */
225         /* Id from our table after sending the request             */
226         if (this && (this->Req == UREMOVE) && this->Id) {
227                 Id = this->Id;
228                 e_no = a->IdTable[Id];
229                 free_entity(a, e_no);
230                 for (i = 0; i < 256; i++)
231                 {
232                         if (a->FlowControlIdTable[i] == Id)
233                                 a->FlowControlIdTable[i] = 0;
234                 }
235                 a->IdTable[Id] = 0;
236                 this->Id = 0;
237         }
238 }
239 static byte pr_ready(ADAPTER *a)
240 {
241         byte ReadyCount;
242         ReadyCount = (byte)(a->ram_in(a, &PR_RAM->ReqOutput) -
243                             a->ram_in(a, &PR_RAM->ReqInput));
244         if (!ReadyCount) {
245                 if (!a->ReadyInt) {
246                         a->ram_inc(a, &PR_RAM->ReadyInt);
247                         a->ReadyInt++;
248                 }
249         }
250         return ReadyCount;
251 }
252 /*------------------------------------------------------------------*/
253 /* isdn interrupt handler                                           */
254 /*------------------------------------------------------------------*/
255 byte pr_dpc(ADAPTER *a)
256 {
257         byte Count;
258         RC *RcIn;
259         IND *IndIn;
260         byte c;
261         byte RNRId;
262         byte Rc;
263         byte Ind;
264         /* if return codes are available ...                        */
265         if ((Count = a->ram_in(a, &PR_RAM->RcOutput)) != 0) {
266                 dtrc(dprintf("#Rc=%x", Count));
267                 /* get the buffer address of the first return code          */
268                 RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextRc)];
269                 /* for all return codes do ...                              */
270                 while (Count--) {
271                         if ((Rc = a->ram_in(a, &RcIn->Rc)) != 0) {
272                                 dword tmp[2];
273                                 /*
274                                   Get extended information, associated with return code
275                                 */
276                                 a->ram_in_buffer(a,
277                                                  &RcIn->Reserved2[0],
278                                                  (byte *)&tmp[0],
279                                                  8);
280                                 /* call return code handler, if it is not our return code   */
281                                 /* the handler returns 2                                    */
282                                 /* for all return codes we process, we clear the Rc field   */
283                                 isdn_rc(a,
284                                         Rc,
285                                         a->ram_in(a, &RcIn->RcId),
286                                         a->ram_in(a, &RcIn->RcCh),
287                                         a->ram_inw(a, &RcIn->Reference),
288                                         tmp[0],  /* type of extended information */
289                                         tmp[1]); /* extended information        */
290                                 a->ram_out(a, &RcIn->Rc, 0);
291                         }
292                         /* get buffer address of next return code                   */
293                         RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &RcIn->next)];
294                 }
295                 /* clear all return codes (no chaining!)                    */
296                 a->ram_out(a, &PR_RAM->RcOutput, 0);
297                 /* call output function                                     */
298                 pr_out(a);
299         }
300         /* clear RNR flag                                           */
301         RNRId = 0;
302         /* if indications are available ...                         */
303         if ((Count = a->ram_in(a, &PR_RAM->IndOutput)) != 0) {
304                 dtrc(dprintf("#Ind=%x", Count));
305                 /* get the buffer address of the first indication           */
306                 IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextInd)];
307                 /* for all indications do ...                               */
308                 while (Count--) {
309                         /* if the application marks an indication as RNR, all       */
310                         /* indications from the same Id delivered in this interrupt */
311                         /* are marked RNR                                           */
312                         if (RNRId && RNRId == a->ram_in(a, &IndIn->IndId)) {
313                                 a->ram_out(a, &IndIn->Ind, 0);
314                                 a->ram_out(a, &IndIn->RNR, true);
315                         }
316                         else {
317                                 Ind = a->ram_in(a, &IndIn->Ind);
318                                 if (Ind) {
319                                         RNRId = 0;
320                                         /* call indication handler, a return value of 2 means chain */
321                                         /* a return value of 1 means RNR                            */
322                                         /* for all indications we process, we clear the Ind field   */
323                                         c = isdn_ind(a,
324                                                      Ind,
325                                                      a->ram_in(a, &IndIn->IndId),
326                                                      a->ram_in(a, &IndIn->IndCh),
327                                                      &IndIn->RBuffer,
328                                                      a->ram_in(a, &IndIn->MInd),
329                                                      a->ram_inw(a, &IndIn->MLength));
330                                         if (c == 1) {
331                                                 dtrc(dprintf("RNR"));
332                                                 a->ram_out(a, &IndIn->Ind, 0);
333                                                 RNRId = a->ram_in(a, &IndIn->IndId);
334                                                 a->ram_out(a, &IndIn->RNR, true);
335                                         }
336                                 }
337                         }
338                         /* get buffer address of next indication                    */
339                         IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &IndIn->next)];
340                 }
341                 a->ram_out(a, &PR_RAM->IndOutput, 0);
342         }
343         return false;
344 }
345 byte scom_test_int(ADAPTER *a)
346 {
347         return a->ram_in(a, (void *)0x3fe);
348 }
349 void scom_clear_int(ADAPTER *a)
350 {
351         a->ram_out(a, (void *)0x3fe, 0);
352 }
353 /*------------------------------------------------------------------*/
354 /* return code handler                                              */
355 /*------------------------------------------------------------------*/
356 static byte isdn_rc(ADAPTER *a,
357                     byte Rc,
358                     byte Id,
359                     byte Ch,
360                     word Ref,
361                     dword extended_info_type,
362                     dword extended_info)
363 {
364         ENTITY *this;
365         byte e_no;
366         word i;
367         int cancel_rc;
368 #ifdef USE_EXTENDED_DEBUGS
369         {
370                 DBG_TRC(("<A%d Id=0x%x Rc=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, Id, Rc))
371                         }
372 #else
373         dbug(dprintf("isdn_rc(Rc=%x,Id=%x,Ch=%x)", Rc, Id, Ch));
374 #endif
375         /* check for ready interrupt                                */
376         if (Rc == READY_INT) {
377                 xdi_xlog_rc_event(XDI_A_NR(a), Id, Ch, Rc, 0, 0);
378                 if (a->ReadyInt) {
379                         a->ReadyInt--;
380                         return 0;
381                 }
382                 return 2;
383         }
384         /* if we know this Id ...                                   */
385         e_no = a->IdTable[Id];
386         if (e_no) {
387                 this = entity_ptr(a, e_no);
388                 xdi_xlog_rc_event(XDI_A_NR(a), Id, Ch, Rc, 0, a->IdTypeTable[this->No]);
389                 this->RcCh = Ch;
390                 /* if it is a return code to a REMOVE request, remove the   */
391                 /* Id from our table                                        */
392                 if ((a->misc_flags_table[e_no] & DIVA_MISC_FLAGS_REMOVE_PENDING) &&
393                     (Rc == OK)) {
394                         if (a->IdTypeTable[e_no] == NL_ID) {
395                                 if (a->RcExtensionSupported &&
396                                     (extended_info_type != DIVA_RC_TYPE_REMOVE_COMPLETE)) {
397                                         dtrc(dprintf("XDI: N-REMOVE, A(%02x) Id:%02x, ignore RC=OK",
398                                                      XDI_A_NR(a), Id));
399                                         return (0);
400                                 }
401                                 if (extended_info_type == DIVA_RC_TYPE_REMOVE_COMPLETE)
402                                         a->RcExtensionSupported = true;
403                         }
404                         a->misc_flags_table[e_no] &= ~DIVA_MISC_FLAGS_REMOVE_PENDING;
405                         a->misc_flags_table[e_no] &= ~DIVA_MISC_FLAGS_NO_RC_CANCELLING;
406                         free_entity(a, e_no);
407                         for (i = 0; i < 256; i++)
408                         {
409                                 if (a->FlowControlIdTable[i] == Id)
410                                         a->FlowControlIdTable[i] = 0;
411                         }
412                         a->IdTable[Id] = 0;
413                         this->Id = 0;
414                         /* ---------------------------------------------------------------
415                            If we send N_DISC or N_DISK_ACK after we have received OK_FC
416                            then the card will respond with OK_FC and later with RC==OK.
417                            If we send N_REMOVE in this state we will receive only RC==OK
418                            This will create the state in that the XDI is waiting for the
419                            additional RC and does not delivery the RC to the client. This
420                            code corrects the counter of outstanding RC's in this case.
421                            --------------------------------------------------------------- */
422                         if ((this->More & XMOREC) > 1) {
423                                 this->More &= ~XMOREC;
424                                 this->More |= 1;
425                                 dtrc(dprintf("XDI: correct MORE on REMOVE A(%02x) Id:%02x",
426                                              XDI_A_NR(a), Id));
427                         }
428                 }
429                 if (Rc == OK_FC) {
430                         a->FlowControlIdTable[Ch] = Id;
431                         a->FlowControlSkipTable[Ch] = false;
432                         this->Rc = Rc;
433                         this->More &= ~(XBUSY | XMOREC);
434                         this->complete = 0xff;
435                         xdi_xlog_rc_event(XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
436                         CALLBACK(a, this);
437                         return 0;
438                 }
439                 /*
440                   New protocol code sends return codes that comes from release
441                   of flow control condition marked with DIVA_RC_TYPE_OK_FC extended
442                   information element type.
443                   If like return code arrives then application is able to process
444                   all return codes self and XDI should not cances return codes.
445                   This return code does not decrement XMOREC partial return code
446                   counter due to fact that it was no request for this return code,
447                   also XMOREC was not incremented.
448                 */
449                 if (extended_info_type == DIVA_RC_TYPE_OK_FC) {
450                         a->misc_flags_table[e_no] |= DIVA_MISC_FLAGS_NO_RC_CANCELLING;
451                         this->Rc = Rc;
452                         this->complete = 0xff;
453                         xdi_xlog_rc_event(XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
454                         DBG_TRC(("XDI OK_FC A(%02x) Id:%02x Ch:%02x Rc:%02x",
455                                  XDI_A_NR(a), Id, Ch, Rc))
456                                 CALLBACK(a, this);
457                         return 0;
458                 }
459                 cancel_rc = !(a->misc_flags_table[e_no] & DIVA_MISC_FLAGS_NO_RC_CANCELLING);
460                 if (cancel_rc && (a->FlowControlIdTable[Ch] == Id))
461                 {
462                         a->FlowControlIdTable[Ch] = 0;
463                         if ((Rc != OK) || !a->FlowControlSkipTable[Ch])
464                         {
465                                 this->Rc = Rc;
466                                 if (Ch == this->ReqCh)
467                                 {
468                                         this->More &= ~(XBUSY | XMOREC);
469                                         this->complete = 0xff;
470                                 }
471                                 xdi_xlog_rc_event(XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
472                                 CALLBACK(a, this);
473                         }
474                         return 0;
475                 }
476                 if (this->More & XMOREC)
477                         this->More--;
478                 /* call the application callback function                   */
479                 if (((!cancel_rc) || (this->More & XMOREF)) && !(this->More & XMOREC)) {
480                         this->Rc = Rc;
481                         this->More &= ~XBUSY;
482                         this->complete = 0xff;
483                         xdi_xlog_rc_event(XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
484                         CALLBACK(a, this);
485                 }
486                 return 0;
487         }
488         /* if it's an ASSIGN return code check if it's a return     */
489         /* code to an ASSIGN request from us                        */
490         if ((Rc & 0xf0) == ASSIGN_RC) {
491                 e_no = get_assign(a, Ref);
492                 if (e_no) {
493                         this = entity_ptr(a, e_no);
494                         this->Id = Id;
495                         xdi_xlog_rc_event(XDI_A_NR(a), Id, Ch, Rc, 2, a->IdTypeTable[this->No]);
496                         /* call the application callback function                   */
497                         this->Rc = Rc;
498                         this->More &= ~XBUSY;
499                         this->complete = 0xff;
500 #if defined(DIVA_ISTREAM) /* { */
501                         if ((Rc == ASSIGN_OK) && a->ram_offset &&
502                             (a->IdTypeTable[this->No] == NL_ID) &&
503                             ((extended_info_type == DIVA_RC_TYPE_RX_DMA) ||
504                              (extended_info_type == DIVA_RC_TYPE_CMA_PTR)) &&
505                             extended_info) {
506                                 dword offset = (*(a->ram_offset)) (a);
507                                 dword tmp[2];
508                                 extended_info -= offset;
509 #ifdef PLATFORM_GT_32BIT
510                                 a->ram_in_dw(a, (void *)ULongToPtr(extended_info), (dword *)&tmp[0], 2);
511 #else
512                                 a->ram_in_dw(a, (void *)extended_info, (dword *)&tmp[0], 2);
513 #endif
514                                 a->tx_stream[Id]  = tmp[0];
515                                 a->rx_stream[Id]  = tmp[1];
516                                 if (extended_info_type == DIVA_RC_TYPE_RX_DMA) {
517                                         DBG_TRC(("Id=0x%x RxDMA=%08x:%08x",
518                                                  Id, a->tx_stream[Id], a->rx_stream[Id]))
519                                                 a->misc_flags_table[this->No] |= DIVA_MISC_FLAGS_RX_DMA;
520                                 } else {
521                                         DBG_TRC(("Id=0x%x CMA=%08x:%08x",
522                                                  Id, a->tx_stream[Id], a->rx_stream[Id]))
523                                                 a->misc_flags_table[this->No] &= ~DIVA_MISC_FLAGS_RX_DMA;
524                                         a->rx_pos[Id]     = 0;
525                                         a->rx_stream[Id] -= offset;
526                                 }
527                                 a->tx_pos[Id]     = 0;
528                                 a->tx_stream[Id] -= offset;
529                         } else {
530                                 a->tx_stream[Id] = 0;
531                                 a->rx_stream[Id] = 0;
532                                 a->misc_flags_table[this->No] &= ~DIVA_MISC_FLAGS_RX_DMA;
533                         }
534 #endif /* } */
535                         CALLBACK(a, this);
536                         if (Rc == ASSIGN_OK) {
537                                 a->IdTable[Id] = e_no;
538                         }
539                         else
540                         {
541                                 free_entity(a, e_no);
542                                 for (i = 0; i < 256; i++)
543                                 {
544                                         if (a->FlowControlIdTable[i] == Id)
545                                                 a->FlowControlIdTable[i] = 0;
546                                 }
547                                 a->IdTable[Id] = 0;
548                                 this->Id = 0;
549                         }
550                         return 1;
551                 }
552         }
553         return 2;
554 }
555 /*------------------------------------------------------------------*/
556 /* indication handler                                               */
557 /*------------------------------------------------------------------*/
558 static byte isdn_ind(ADAPTER *a,
559                      byte Ind,
560                      byte Id,
561                      byte Ch,
562                      PBUFFER *RBuffer,
563                      byte MInd,
564                      word MLength)
565 {
566         ENTITY *this;
567         word clength;
568         word offset;
569         BUFFERS *R;
570         byte *cma = NULL;
571 #ifdef USE_EXTENDED_DEBUGS
572         {
573                 DBG_TRC(("<A%d Id=0x%x Ind=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, Id, Ind))
574                         }
575 #else
576         dbug(dprintf("isdn_ind(Ind=%x,Id=%x,Ch=%x)", Ind, Id, Ch));
577 #endif
578         if (a->IdTable[Id]) {
579                 this = entity_ptr(a, a->IdTable[Id]);
580                 this->IndCh = Ch;
581                 xdi_xlog_ind(XDI_A_NR(a), Id, Ch, Ind,
582                              0/* rnr_valid */, 0 /* rnr */, a->IdTypeTable[this->No]);
583                 /* if the Receive More flag is not yet set, this is the     */
584                 /* first buffer of the packet                               */
585                 if (this->RCurrent == 0xff) {
586                         /* check for receive buffer chaining                        */
587                         if (Ind == this->MInd) {
588                                 this->complete = 0;
589                                 this->Ind = MInd;
590                         }
591                         else {
592                                 this->complete = 1;
593                                 this->Ind = Ind;
594                         }
595                         /* call the application callback function for the receive   */
596                         /* look ahead                                               */
597                         this->RLength = MLength;
598 #if defined(DIVA_ISTREAM)
599                         if ((a->rx_stream[this->Id] ||
600                              (a->misc_flags_table[this->No] & DIVA_MISC_FLAGS_RX_DMA)) &&
601                             ((Ind == N_DATA) ||
602                              (a->protocol_capabilities & PROTCAP_CMA_ALLPR))) {
603                                 PISDN_ADAPTER IoAdapter = (PISDN_ADAPTER)a->io;
604                                 if (a->misc_flags_table[this->No] & DIVA_MISC_FLAGS_RX_DMA) {
605 #if defined(DIVA_IDI_RX_DMA)
606                                         dword d;
607                                         diva_get_dma_map_entry(\
608                                                 (struct _diva_dma_map_entry *)IoAdapter->dma_map,
609                                                 (int)a->rx_stream[this->Id], (void **)&cma, &d);
610 #else
611                                         cma = &a->stream_buffer[0];
612                                         cma[0] = cma[1] = cma[2] = cma[3] = 0;
613 #endif
614                                         this->RLength = MLength = (word)*(dword *)cma;
615                                         cma += 4;
616                                 } else {
617                                         int final = 0;
618                                         cma = &a->stream_buffer[0];
619                                         this->RLength = MLength = (word)diva_istream_read(a,
620                                                                                           Id,
621                                                                                           cma,
622                                                                                           sizeof(a->stream_buffer),
623                                                                                           &final, NULL, NULL);
624                                 }
625                                 IoAdapter->RBuffer.length = min(MLength, (word)270);
626                                 if (IoAdapter->RBuffer.length != MLength) {
627                                         this->complete = 0;
628                                 } else {
629                                         this->complete = 1;
630                                 }
631                                 memcpy(IoAdapter->RBuffer.P, cma, IoAdapter->RBuffer.length);
632                                 this->RBuffer = (DBUFFER *)&IoAdapter->RBuffer;
633                         }
634 #endif
635                         if (!cma) {
636                                 a->ram_look_ahead(a, RBuffer, this);
637                         }
638                         this->RNum = 0;
639                         CALLBACK(a, this);
640                         /* map entity ptr, selector could be re-mapped by call to   */
641                         /* IDI from within callback                                 */
642                         this = entity_ptr(a, a->IdTable[Id]);
643                         xdi_xlog_ind(XDI_A_NR(a), Id, Ch, Ind,
644                                      1/* rnr_valid */, this->RNR/* rnr */, a->IdTypeTable[this->No]);
645                         /* check for RNR                                            */
646                         if (this->RNR == 1) {
647                                 this->RNR = 0;
648                                 return 1;
649                         }
650                         /* if no buffers are provided by the application, the       */
651                         /* application want to copy the data itself including       */
652                         /* N_MDATA/LL_MDATA chaining                                */
653                         if (!this->RNR && !this->RNum) {
654                                 xdi_xlog_ind(XDI_A_NR(a), Id, Ch, Ind,
655                                              2/* rnr_valid */, 0/* rnr */, a->IdTypeTable[this->No]);
656                                 return 0;
657                         }
658                         /* if there is no RNR, set the More flag                    */
659                         this->RCurrent = 0;
660                         this->ROffset = 0;
661                 }
662                 if (this->RNR == 2) {
663                         if (Ind != this->MInd) {
664                                 this->RCurrent = 0xff;
665                                 this->RNR = 0;
666                         }
667                         return 0;
668                 }
669                 /* if we have received buffers from the application, copy   */
670                 /* the data into these buffers                              */
671                 offset = 0;
672                 R = PTR_R(a, this);
673                 do {
674                         if (this->ROffset == R[this->RCurrent].PLength) {
675                                 this->ROffset = 0;
676                                 this->RCurrent++;
677                         }
678                         if (cma) {
679                                 clength = min(MLength, (word)(R[this->RCurrent].PLength-this->ROffset));
680                         } else {
681                                 clength = min(a->ram_inw(a, &RBuffer->length)-offset,
682                                               R[this->RCurrent].PLength-this->ROffset);
683                         }
684                         if (R[this->RCurrent].P) {
685                                 if (cma) {
686                                         memcpy(PTR_P(a, this, &R[this->RCurrent].P[this->ROffset]),
687                                                &cma[offset],
688                                                clength);
689                                 } else {
690                                         a->ram_in_buffer(a,
691                                                          &RBuffer->P[offset],
692                                                          PTR_P(a, this, &R[this->RCurrent].P[this->ROffset]),
693                                                          clength);
694                                 }
695                         }
696                         offset += clength;
697                         this->ROffset += clength;
698                         if (cma) {
699                                 if (offset >= MLength) {
700                                         break;
701                                 }
702                                 continue;
703                         }
704                 } while (offset < (a->ram_inw(a, &RBuffer->length)));
705                 /* if it's the last buffer of the packet, call the          */
706                 /* application callback function for the receive complete   */
707                 /* call                                                     */
708                 if (Ind != this->MInd) {
709                         R[this->RCurrent].PLength = this->ROffset;
710                         if (this->ROffset) this->RCurrent++;
711                         this->RNum = this->RCurrent;
712                         this->RCurrent = 0xff;
713                         this->Ind = Ind;
714                         this->complete = 2;
715                         xdi_xlog_ind(XDI_A_NR(a), Id, Ch, Ind,
716                                      3/* rnr_valid */, 0/* rnr */, a->IdTypeTable[this->No]);
717                         CALLBACK(a, this);
718                 }
719                 return 0;
720         }
721         return 2;
722 }
723 #if defined(XDI_USE_XLOG)
724 /* -----------------------------------------------------------
725    This function works in the same way as xlog on the
726    active board
727    ----------------------------------------------------------- */
728 static void xdi_xlog(byte *msg, word code, int length) {
729         xdi_dbg_xlog("\x00\x02", msg, code, length);
730 }
731 #endif
732 /* -----------------------------------------------------------
733    This function writes the information about the Return Code
734    processing in the trace buffer. Trace ID is 221.
735    INPUT:
736    Adapter - system unicue adapter number (0 ... 255)
737    Id      - Id of the entity that had sent this return code
738    Ch      - Channel of the entity that had sent this return code
739    Rc      - return code value
740    cb:       (0...2)
741    switch (cb) {
742    case 0: printf ("DELIVERY"); break;
743    case 1: printf ("CALLBACK"); break;
744    case 2: printf ("ASSIGN"); break;
745    }
746    DELIVERY - have entered isdn_rc with this RC
747    CALLBACK - about to make callback to the application
748    for this RC
749    ASSIGN   - about to make callback for RC that is result
750    of ASSIGN request. It is no DELIVERY message
751    before of this message
752    type   - the Id that was sent by the ASSIGN of this entity.
753    This should be global Id like NL_ID, DSIG_ID, MAN_ID.
754    An unknown Id will cause "?-" in the front of the request.
755    In this case the log.c is to be extended.
756    ----------------------------------------------------------- */
757 static void xdi_xlog_rc_event(byte Adapter,
758                               byte Id, byte Ch, byte Rc, byte cb, byte type) {
759 #if defined(XDI_USE_XLOG)
760         word LogInfo[4];
761         PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8)));
762         PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8)));
763         PUT_WORD(&LogInfo[2], ((word)Rc | (word)(type << 8)));
764         PUT_WORD(&LogInfo[3], cb);
765         xdi_xlog((byte *)&LogInfo[0], 221, sizeof(LogInfo));
766 #endif
767 }
768 /* ------------------------------------------------------------------------
769    This function writes the information about the request processing
770    in the trace buffer. Trace ID is 220.
771    INPUT:
772    Adapter - system unicue adapter number (0 ... 255)
773    Id      - Id of the entity that had sent this request
774    Ch      - Channel of the entity that had sent this request
775    Req     - Code of the request
776    type    - the Id that was sent by the ASSIGN of this entity.
777    This should be global Id like NL_ID, DSIG_ID, MAN_ID.
778    An unknown Id will cause "?-" in the front of the request.
779    In this case the log.c is to be extended.
780    ------------------------------------------------------------------------ */
781 static void xdi_xlog_request(byte Adapter, byte Id,
782                              byte Ch, byte Req, byte type) {
783 #if defined(XDI_USE_XLOG)
784         word LogInfo[3];
785         PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8)));
786         PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8)));
787         PUT_WORD(&LogInfo[2], ((word)Req | (word)(type << 8)));
788         xdi_xlog((byte *)&LogInfo[0], 220, sizeof(LogInfo));
789 #endif
790 }
791 /* ------------------------------------------------------------------------
792    This function writes the information about the indication processing
793    in the trace buffer. Trace ID is 222.
794    INPUT:
795    Adapter - system unicue adapter number (0 ... 255)
796    Id      - Id of the entity that had sent this indication
797    Ch      - Channel of the entity that had sent this indication
798    Ind     - Code of the indication
799    rnr_valid: (0 .. 3) supported
800    switch (rnr_valid) {
801    case 0: printf ("DELIVERY"); break;
802    case 1: printf ("RNR=%d", rnr);
803    case 2: printf ("RNum=0");
804    case 3: printf ("COMPLETE");
805    }
806    DELIVERY - indication entered isdn_rc function
807    RNR=...  - application had returned RNR=... after the
808    look ahead callback
809    RNum=0   - application had not returned any buffer to copy
810    this indication and will copy it self
811    COMPLETE - XDI had copied the data to the buffers provided
812    bu the application and is about to issue the
813    final callback
814    rnr:  Look case 1 of the rnr_valid
815    type: the Id that was sent by the ASSIGN of this entity. This should
816    be global Id like NL_ID, DSIG_ID, MAN_ID. An unknown Id will
817    cause "?-" in the front of the request. In this case the
818    log.c is to be extended.
819    ------------------------------------------------------------------------ */
820 static void xdi_xlog_ind(byte Adapter,
821                          byte Id,
822                          byte Ch,
823                          byte Ind,
824                          byte rnr_valid,
825                          byte rnr,
826                          byte type) {
827 #if defined(XDI_USE_XLOG)
828         word LogInfo[4];
829         PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8)));
830         PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8)));
831         PUT_WORD(&LogInfo[2], ((word)Ind | (word)(type << 8)));
832         PUT_WORD(&LogInfo[3], ((word)rnr | (word)(rnr_valid << 8)));
833         xdi_xlog((byte *)&LogInfo[0], 222, sizeof(LogInfo));
834 #endif
835 }