Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / isdn / hardware / eicon / di.c
diff --git a/kernel/drivers/isdn/hardware/eicon/di.c b/kernel/drivers/isdn/hardware/eicon/di.c
new file mode 100644 (file)
index 0000000..cd3fba1
--- /dev/null
@@ -0,0 +1,835 @@
+
+/*
+ *
+ Copyright (c) Eicon Networks, 2002.
+ *
+ This source file is supplied for the use with
+ Eicon Networks range of DIVA Server Adapters.
+ *
+ Eicon File Revision :    2.1
+ *
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+ *
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+ *
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include "platform.h"
+#include "pc.h"
+#include "pr_pc.h"
+#include "di_defs.h"
+#include "di.h"
+#if !defined USE_EXTENDED_DEBUGS
+#include "dimaint.h"
+#else
+#define dprintf
+#endif
+#include "io.h"
+#include "dfifo.h"
+#define PR_RAM  ((struct pr_ram *)0)
+#define RAM ((struct dual *)0)
+/*------------------------------------------------------------------*/
+/* local function prototypes                                        */
+/*------------------------------------------------------------------*/
+void pr_out(ADAPTER *a);
+byte pr_dpc(ADAPTER *a);
+static byte pr_ready(ADAPTER *a);
+static byte isdn_rc(ADAPTER *, byte, byte, byte, word, dword, dword);
+static byte isdn_ind(ADAPTER *, byte, byte, byte, PBUFFER *, byte, word);
+/* -----------------------------------------------------------------
+   Functions used for the extended XDI Debug
+   macros
+   global convergence counter (used by all adapters)
+   Look by the implementation part of the functions
+   about the parameters.
+   If you change the dubugging parameters, then you should update
+   the aididbg.doc in the IDI doc's.
+   ----------------------------------------------------------------- */
+#if defined(XDI_USE_XLOG)
+#define XDI_A_NR(_x_) ((byte)(((ISDN_ADAPTER *)(_x_->io))->ANum))
+static void xdi_xlog(byte *msg, word code, int length);
+static byte xdi_xlog_sec = 0;
+#else
+#define XDI_A_NR(_x_) ((byte)0)
+#endif
+static void xdi_xlog_rc_event(byte Adapter,
+                             byte Id, byte Ch, byte Rc, byte cb, byte type);
+static void xdi_xlog_request(byte Adapter, byte Id,
+                            byte Ch, byte Req, byte type);
+static void xdi_xlog_ind(byte Adapter,
+                        byte Id,
+                        byte Ch,
+                        byte Ind,
+                        byte rnr_valid,
+                        byte rnr,
+                        byte type);
+/*------------------------------------------------------------------*/
+/* output function                                                  */
+/*------------------------------------------------------------------*/
+void pr_out(ADAPTER *a)
+{
+       byte e_no;
+       ENTITY *this = NULL;
+       BUFFERS *X;
+       word length;
+       word i;
+       word clength;
+       REQ *ReqOut;
+       byte more;
+       byte ReadyCount;
+       byte ReqCount;
+       byte Id;
+       dtrc(dprintf("pr_out"));
+       /* while a request is pending ...                           */
+       e_no = look_req(a);
+       if (!e_no)
+       {
+               dtrc(dprintf("no_req"));
+               return;
+       }
+       ReadyCount = pr_ready(a);
+       if (!ReadyCount)
+       {
+               dtrc(dprintf("not_ready"));
+               return;
+       }
+       ReqCount = 0;
+       while (e_no && ReadyCount) {
+               next_req(a);
+               this = entity_ptr(a, e_no);
+#ifdef USE_EXTENDED_DEBUGS
+               if (!this)
+               {
+                       DBG_FTL(("XDI: [%02x] !A%d ==> NULL entity ptr - try to ignore",
+                                xdi_xlog_sec++, (int)((ISDN_ADAPTER *)a->io)->ANum))
+                               e_no = look_req(a);
+                       ReadyCount--;
+                       continue;
+               }
+               {
+                       DBG_TRC((">A%d Id=0x%x Req=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, this->Id, this->Req))
+                               }
+#else
+               dbug(dprintf("out:Req=%x,Id=%x,Ch=%x", this->Req, this->Id, this->ReqCh));
+#endif
+               /* get address of next available request buffer             */
+               ReqOut = (REQ *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextReq)];
+#if defined(DIVA_ISTREAM)
+               if (!(a->tx_stream[this->Id]   &&
+                     this->Req == N_DATA)) {
+#endif
+                       /* now copy the data from the current data buffer into the  */
+                       /* adapters request buffer                                  */
+                       length = 0;
+                       i = this->XCurrent;
+                       X = PTR_X(a, this);
+                       while (i < this->XNum && length < 270) {
+                               clength = min((word)(270 - length), (word)(X[i].PLength-this->XOffset));
+                               a->ram_out_buffer(a,
+                                                 &ReqOut->XBuffer.P[length],
+                                                 PTR_P(a, this, &X[i].P[this->XOffset]),
+                                                 clength);
+                               length += clength;
+                               this->XOffset += clength;
+                               if (this->XOffset == X[i].PLength) {
+                                       this->XCurrent = (byte)++i;
+                                       this->XOffset = 0;
+                               }
+                       }
+#if defined(DIVA_ISTREAM)
+               } else { /* Use CMA extension in order to transfer data to the card */
+                       i = this->XCurrent;
+                       X = PTR_X(a, this);
+                       while (i < this->XNum) {
+                               diva_istream_write(a,
+                                                  this->Id,
+                                                  PTR_P(a, this, &X[i].P[0]),
+                                                  X[i].PLength,
+                                                  ((i + 1) == this->XNum),
+                                                  0, 0);
+                               this->XCurrent = (byte)++i;
+                       }
+                       length = 0;
+               }
+#endif
+               a->ram_outw(a, &ReqOut->XBuffer.length, length);
+               a->ram_out(a, &ReqOut->ReqId, this->Id);
+               a->ram_out(a, &ReqOut->ReqCh, this->ReqCh);
+               /* if it's a specific request (no ASSIGN) ...                */
+               if (this->Id & 0x1f) {
+                       /* if buffers are left in the list of data buffers do       */
+                       /* do chaining (LL_MDATA, N_MDATA)                          */
+                       this->More++;
+                       if (i < this->XNum && this->MInd) {
+                               xdi_xlog_request(XDI_A_NR(a), this->Id, this->ReqCh, this->MInd,
+                                                a->IdTypeTable[this->No]);
+                               a->ram_out(a, &ReqOut->Req, this->MInd);
+                               more = true;
+                       }
+                       else {
+                               xdi_xlog_request(XDI_A_NR(a), this->Id, this->ReqCh, this->Req,
+                                                a->IdTypeTable[this->No]);
+                               this->More |= XMOREF;
+                               a->ram_out(a, &ReqOut->Req, this->Req);
+                               more = false;
+                               if (a->FlowControlIdTable[this->ReqCh] == this->Id)
+                                       a->FlowControlSkipTable[this->ReqCh] = true;
+                               /*
+                                 Note that remove request was sent to the card
+                               */
+                               if (this->Req == REMOVE) {
+                                       a->misc_flags_table[e_no] |= DIVA_MISC_FLAGS_REMOVE_PENDING;
+                               }
+                       }
+                       /* if we did chaining, this entity is put back into the     */
+                       /* request queue                                            */
+                       if (more) {
+                               req_queue(a, this->No);
+                       }
+               }
+               /* else it's a ASSIGN                                       */
+               else {
+                       /* save the request code used for buffer chaining           */
+                       this->MInd = 0;
+                       if (this->Id == BLLC_ID) this->MInd = LL_MDATA;
+                       if (this->Id == NL_ID ||
+                           this->Id == TASK_ID ||
+                           this->Id == MAN_ID
+                               ) this->MInd = N_MDATA;
+                       /* send the ASSIGN                                          */
+                       a->IdTypeTable[this->No] = this->Id;
+                       xdi_xlog_request(XDI_A_NR(a), this->Id, this->ReqCh, this->Req, this->Id);
+                       this->More |= XMOREF;
+                       a->ram_out(a, &ReqOut->Req, this->Req);
+                       /* save the reference of the ASSIGN                         */
+                       assign_queue(a, this->No, a->ram_inw(a, &ReqOut->Reference));
+               }
+               a->ram_outw(a, &PR_RAM->NextReq, a->ram_inw(a, &ReqOut->next));
+               ReadyCount--;
+               ReqCount++;
+               e_no = look_req(a);
+       }
+       /* send the filled request buffers to the ISDN adapter      */
+       a->ram_out(a, &PR_RAM->ReqInput,
+                  (byte)(a->ram_in(a, &PR_RAM->ReqInput) + ReqCount));
+       /* if it is a 'unreturncoded' UREMOVE request, remove the  */
+       /* Id from our table after sending the request             */
+       if (this && (this->Req == UREMOVE) && this->Id) {
+               Id = this->Id;
+               e_no = a->IdTable[Id];
+               free_entity(a, e_no);
+               for (i = 0; i < 256; i++)
+               {
+                       if (a->FlowControlIdTable[i] == Id)
+                               a->FlowControlIdTable[i] = 0;
+               }
+               a->IdTable[Id] = 0;
+               this->Id = 0;
+       }
+}
+static byte pr_ready(ADAPTER *a)
+{
+       byte ReadyCount;
+       ReadyCount = (byte)(a->ram_in(a, &PR_RAM->ReqOutput) -
+                           a->ram_in(a, &PR_RAM->ReqInput));
+       if (!ReadyCount) {
+               if (!a->ReadyInt) {
+                       a->ram_inc(a, &PR_RAM->ReadyInt);
+                       a->ReadyInt++;
+               }
+       }
+       return ReadyCount;
+}
+/*------------------------------------------------------------------*/
+/* isdn interrupt handler                                           */
+/*------------------------------------------------------------------*/
+byte pr_dpc(ADAPTER *a)
+{
+       byte Count;
+       RC *RcIn;
+       IND *IndIn;
+       byte c;
+       byte RNRId;
+       byte Rc;
+       byte Ind;
+       /* if return codes are available ...                        */
+       if ((Count = a->ram_in(a, &PR_RAM->RcOutput)) != 0) {
+               dtrc(dprintf("#Rc=%x", Count));
+               /* get the buffer address of the first return code          */
+               RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextRc)];
+               /* for all return codes do ...                              */
+               while (Count--) {
+                       if ((Rc = a->ram_in(a, &RcIn->Rc)) != 0) {
+                               dword tmp[2];
+                               /*
+                                 Get extended information, associated with return code
+                               */
+                               a->ram_in_buffer(a,
+                                                &RcIn->Reserved2[0],
+                                                (byte *)&tmp[0],
+                                                8);
+                               /* call return code handler, if it is not our return code   */
+                               /* the handler returns 2                                    */
+                               /* for all return codes we process, we clear the Rc field   */
+                               isdn_rc(a,
+                                       Rc,
+                                       a->ram_in(a, &RcIn->RcId),
+                                       a->ram_in(a, &RcIn->RcCh),
+                                       a->ram_inw(a, &RcIn->Reference),
+                                       tmp[0],  /* type of extended information */
+                                       tmp[1]); /* extended information        */
+                               a->ram_out(a, &RcIn->Rc, 0);
+                       }
+                       /* get buffer address of next return code                   */
+                       RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &RcIn->next)];
+               }
+               /* clear all return codes (no chaining!)                    */
+               a->ram_out(a, &PR_RAM->RcOutput, 0);
+               /* call output function                                     */
+               pr_out(a);
+       }
+       /* clear RNR flag                                           */
+       RNRId = 0;
+       /* if indications are available ...                         */
+       if ((Count = a->ram_in(a, &PR_RAM->IndOutput)) != 0) {
+               dtrc(dprintf("#Ind=%x", Count));
+               /* get the buffer address of the first indication           */
+               IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextInd)];
+               /* for all indications do ...                               */
+               while (Count--) {
+                       /* if the application marks an indication as RNR, all       */
+                       /* indications from the same Id delivered in this interrupt */
+                       /* are marked RNR                                           */
+                       if (RNRId && RNRId == a->ram_in(a, &IndIn->IndId)) {
+                               a->ram_out(a, &IndIn->Ind, 0);
+                               a->ram_out(a, &IndIn->RNR, true);
+                       }
+                       else {
+                               Ind = a->ram_in(a, &IndIn->Ind);
+                               if (Ind) {
+                                       RNRId = 0;
+                                       /* call indication handler, a return value of 2 means chain */
+                                       /* a return value of 1 means RNR                            */
+                                       /* for all indications we process, we clear the Ind field   */
+                                       c = isdn_ind(a,
+                                                    Ind,
+                                                    a->ram_in(a, &IndIn->IndId),
+                                                    a->ram_in(a, &IndIn->IndCh),
+                                                    &IndIn->RBuffer,
+                                                    a->ram_in(a, &IndIn->MInd),
+                                                    a->ram_inw(a, &IndIn->MLength));
+                                       if (c == 1) {
+                                               dtrc(dprintf("RNR"));
+                                               a->ram_out(a, &IndIn->Ind, 0);
+                                               RNRId = a->ram_in(a, &IndIn->IndId);
+                                               a->ram_out(a, &IndIn->RNR, true);
+                                       }
+                               }
+                       }
+                       /* get buffer address of next indication                    */
+                       IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &IndIn->next)];
+               }
+               a->ram_out(a, &PR_RAM->IndOutput, 0);
+       }
+       return false;
+}
+byte scom_test_int(ADAPTER *a)
+{
+       return a->ram_in(a, (void *)0x3fe);
+}
+void scom_clear_int(ADAPTER *a)
+{
+       a->ram_out(a, (void *)0x3fe, 0);
+}
+/*------------------------------------------------------------------*/
+/* return code handler                                              */
+/*------------------------------------------------------------------*/
+static byte isdn_rc(ADAPTER *a,
+                   byte Rc,
+                   byte Id,
+                   byte Ch,
+                   word Ref,
+                   dword extended_info_type,
+                   dword extended_info)
+{
+       ENTITY *this;
+       byte e_no;
+       word i;
+       int cancel_rc;
+#ifdef USE_EXTENDED_DEBUGS
+       {
+               DBG_TRC(("<A%d Id=0x%x Rc=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, Id, Rc))
+                       }
+#else
+       dbug(dprintf("isdn_rc(Rc=%x,Id=%x,Ch=%x)", Rc, Id, Ch));
+#endif
+       /* check for ready interrupt                                */
+       if (Rc == READY_INT) {
+               xdi_xlog_rc_event(XDI_A_NR(a), Id, Ch, Rc, 0, 0);
+               if (a->ReadyInt) {
+                       a->ReadyInt--;
+                       return 0;
+               }
+               return 2;
+       }
+       /* if we know this Id ...                                   */
+       e_no = a->IdTable[Id];
+       if (e_no) {
+               this = entity_ptr(a, e_no);
+               xdi_xlog_rc_event(XDI_A_NR(a), Id, Ch, Rc, 0, a->IdTypeTable[this->No]);
+               this->RcCh = Ch;
+               /* if it is a return code to a REMOVE request, remove the   */
+               /* Id from our table                                        */
+               if ((a->misc_flags_table[e_no] & DIVA_MISC_FLAGS_REMOVE_PENDING) &&
+                   (Rc == OK)) {
+                       if (a->IdTypeTable[e_no] == NL_ID) {
+                               if (a->RcExtensionSupported &&
+                                   (extended_info_type != DIVA_RC_TYPE_REMOVE_COMPLETE)) {
+                                       dtrc(dprintf("XDI: N-REMOVE, A(%02x) Id:%02x, ignore RC=OK",
+                                                    XDI_A_NR(a), Id));
+                                       return (0);
+                               }
+                               if (extended_info_type == DIVA_RC_TYPE_REMOVE_COMPLETE)
+                                       a->RcExtensionSupported = true;
+                       }
+                       a->misc_flags_table[e_no] &= ~DIVA_MISC_FLAGS_REMOVE_PENDING;
+                       a->misc_flags_table[e_no] &= ~DIVA_MISC_FLAGS_NO_RC_CANCELLING;
+                       free_entity(a, e_no);
+                       for (i = 0; i < 256; i++)
+                       {
+                               if (a->FlowControlIdTable[i] == Id)
+                                       a->FlowControlIdTable[i] = 0;
+                       }
+                       a->IdTable[Id] = 0;
+                       this->Id = 0;
+                       /* ---------------------------------------------------------------
+                          If we send N_DISC or N_DISK_ACK after we have received OK_FC
+                          then the card will respond with OK_FC and later with RC==OK.
+                          If we send N_REMOVE in this state we will receive only RC==OK
+                          This will create the state in that the XDI is waiting for the
+                          additional RC and does not delivery the RC to the client. This
+                          code corrects the counter of outstanding RC's in this case.
+                          --------------------------------------------------------------- */
+                       if ((this->More & XMOREC) > 1) {
+                               this->More &= ~XMOREC;
+                               this->More |= 1;
+                               dtrc(dprintf("XDI: correct MORE on REMOVE A(%02x) Id:%02x",
+                                            XDI_A_NR(a), Id));
+                       }
+               }
+               if (Rc == OK_FC) {
+                       a->FlowControlIdTable[Ch] = Id;
+                       a->FlowControlSkipTable[Ch] = false;
+                       this->Rc = Rc;
+                       this->More &= ~(XBUSY | XMOREC);
+                       this->complete = 0xff;
+                       xdi_xlog_rc_event(XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
+                       CALLBACK(a, this);
+                       return 0;
+               }
+               /*
+                 New protocol code sends return codes that comes from release
+                 of flow control condition marked with DIVA_RC_TYPE_OK_FC extended
+                 information element type.
+                 If like return code arrives then application is able to process
+                 all return codes self and XDI should not cances return codes.
+                 This return code does not decrement XMOREC partial return code
+                 counter due to fact that it was no request for this return code,
+                 also XMOREC was not incremented.
+               */
+               if (extended_info_type == DIVA_RC_TYPE_OK_FC) {
+                       a->misc_flags_table[e_no] |= DIVA_MISC_FLAGS_NO_RC_CANCELLING;
+                       this->Rc = Rc;
+                       this->complete = 0xff;
+                       xdi_xlog_rc_event(XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
+                       DBG_TRC(("XDI OK_FC A(%02x) Id:%02x Ch:%02x Rc:%02x",
+                                XDI_A_NR(a), Id, Ch, Rc))
+                               CALLBACK(a, this);
+                       return 0;
+               }
+               cancel_rc = !(a->misc_flags_table[e_no] & DIVA_MISC_FLAGS_NO_RC_CANCELLING);
+               if (cancel_rc && (a->FlowControlIdTable[Ch] == Id))
+               {
+                       a->FlowControlIdTable[Ch] = 0;
+                       if ((Rc != OK) || !a->FlowControlSkipTable[Ch])
+                       {
+                               this->Rc = Rc;
+                               if (Ch == this->ReqCh)
+                               {
+                                       this->More &= ~(XBUSY | XMOREC);
+                                       this->complete = 0xff;
+                               }
+                               xdi_xlog_rc_event(XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
+                               CALLBACK(a, this);
+                       }
+                       return 0;
+               }
+               if (this->More & XMOREC)
+                       this->More--;
+               /* call the application callback function                   */
+               if (((!cancel_rc) || (this->More & XMOREF)) && !(this->More & XMOREC)) {
+                       this->Rc = Rc;
+                       this->More &= ~XBUSY;
+                       this->complete = 0xff;
+                       xdi_xlog_rc_event(XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
+                       CALLBACK(a, this);
+               }
+               return 0;
+       }
+       /* if it's an ASSIGN return code check if it's a return     */
+       /* code to an ASSIGN request from us                        */
+       if ((Rc & 0xf0) == ASSIGN_RC) {
+               e_no = get_assign(a, Ref);
+               if (e_no) {
+                       this = entity_ptr(a, e_no);
+                       this->Id = Id;
+                       xdi_xlog_rc_event(XDI_A_NR(a), Id, Ch, Rc, 2, a->IdTypeTable[this->No]);
+                       /* call the application callback function                   */
+                       this->Rc = Rc;
+                       this->More &= ~XBUSY;
+                       this->complete = 0xff;
+#if defined(DIVA_ISTREAM) /* { */
+                       if ((Rc == ASSIGN_OK) && a->ram_offset &&
+                           (a->IdTypeTable[this->No] == NL_ID) &&
+                           ((extended_info_type == DIVA_RC_TYPE_RX_DMA) ||
+                            (extended_info_type == DIVA_RC_TYPE_CMA_PTR)) &&
+                           extended_info) {
+                               dword offset = (*(a->ram_offset)) (a);
+                               dword tmp[2];
+                               extended_info -= offset;
+#ifdef PLATFORM_GT_32BIT
+                               a->ram_in_dw(a, (void *)ULongToPtr(extended_info), (dword *)&tmp[0], 2);
+#else
+                               a->ram_in_dw(a, (void *)extended_info, (dword *)&tmp[0], 2);
+#endif
+                               a->tx_stream[Id]  = tmp[0];
+                               a->rx_stream[Id]  = tmp[1];
+                               if (extended_info_type == DIVA_RC_TYPE_RX_DMA) {
+                                       DBG_TRC(("Id=0x%x RxDMA=%08x:%08x",
+                                                Id, a->tx_stream[Id], a->rx_stream[Id]))
+                                               a->misc_flags_table[this->No] |= DIVA_MISC_FLAGS_RX_DMA;
+                               } else {
+                                       DBG_TRC(("Id=0x%x CMA=%08x:%08x",
+                                                Id, a->tx_stream[Id], a->rx_stream[Id]))
+                                               a->misc_flags_table[this->No] &= ~DIVA_MISC_FLAGS_RX_DMA;
+                                       a->rx_pos[Id]     = 0;
+                                       a->rx_stream[Id] -= offset;
+                               }
+                               a->tx_pos[Id]     = 0;
+                               a->tx_stream[Id] -= offset;
+                       } else {
+                               a->tx_stream[Id] = 0;
+                               a->rx_stream[Id] = 0;
+                               a->misc_flags_table[this->No] &= ~DIVA_MISC_FLAGS_RX_DMA;
+                       }
+#endif /* } */
+                       CALLBACK(a, this);
+                       if (Rc == ASSIGN_OK) {
+                               a->IdTable[Id] = e_no;
+                       }
+                       else
+                       {
+                               free_entity(a, e_no);
+                               for (i = 0; i < 256; i++)
+                               {
+                                       if (a->FlowControlIdTable[i] == Id)
+                                               a->FlowControlIdTable[i] = 0;
+                               }
+                               a->IdTable[Id] = 0;
+                               this->Id = 0;
+                       }
+                       return 1;
+               }
+       }
+       return 2;
+}
+/*------------------------------------------------------------------*/
+/* indication handler                                               */
+/*------------------------------------------------------------------*/
+static byte isdn_ind(ADAPTER *a,
+                    byte Ind,
+                    byte Id,
+                    byte Ch,
+                    PBUFFER *RBuffer,
+                    byte MInd,
+                    word MLength)
+{
+       ENTITY *this;
+       word clength;
+       word offset;
+       BUFFERS *R;
+       byte *cma = NULL;
+#ifdef USE_EXTENDED_DEBUGS
+       {
+               DBG_TRC(("<A%d Id=0x%x Ind=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, Id, Ind))
+                       }
+#else
+       dbug(dprintf("isdn_ind(Ind=%x,Id=%x,Ch=%x)", Ind, Id, Ch));
+#endif
+       if (a->IdTable[Id]) {
+               this = entity_ptr(a, a->IdTable[Id]);
+               this->IndCh = Ch;
+               xdi_xlog_ind(XDI_A_NR(a), Id, Ch, Ind,
+                            0/* rnr_valid */, 0 /* rnr */, a->IdTypeTable[this->No]);
+               /* if the Receive More flag is not yet set, this is the     */
+               /* first buffer of the packet                               */
+               if (this->RCurrent == 0xff) {
+                       /* check for receive buffer chaining                        */
+                       if (Ind == this->MInd) {
+                               this->complete = 0;
+                               this->Ind = MInd;
+                       }
+                       else {
+                               this->complete = 1;
+                               this->Ind = Ind;
+                       }
+                       /* call the application callback function for the receive   */
+                       /* look ahead                                               */
+                       this->RLength = MLength;
+#if defined(DIVA_ISTREAM)
+                       if ((a->rx_stream[this->Id] ||
+                            (a->misc_flags_table[this->No] & DIVA_MISC_FLAGS_RX_DMA)) &&
+                           ((Ind == N_DATA) ||
+                            (a->protocol_capabilities & PROTCAP_CMA_ALLPR))) {
+                               PISDN_ADAPTER IoAdapter = (PISDN_ADAPTER)a->io;
+                               if (a->misc_flags_table[this->No] & DIVA_MISC_FLAGS_RX_DMA) {
+#if defined(DIVA_IDI_RX_DMA)
+                                       dword d;
+                                       diva_get_dma_map_entry(\
+                                               (struct _diva_dma_map_entry *)IoAdapter->dma_map,
+                                               (int)a->rx_stream[this->Id], (void **)&cma, &d);
+#else
+                                       cma = &a->stream_buffer[0];
+                                       cma[0] = cma[1] = cma[2] = cma[3] = 0;
+#endif
+                                       this->RLength = MLength = (word)*(dword *)cma;
+                                       cma += 4;
+                               } else {
+                                       int final = 0;
+                                       cma = &a->stream_buffer[0];
+                                       this->RLength = MLength = (word)diva_istream_read(a,
+                                                                                         Id,
+                                                                                         cma,
+                                                                                         sizeof(a->stream_buffer),
+                                                                                         &final, NULL, NULL);
+                               }
+                               IoAdapter->RBuffer.length = min(MLength, (word)270);
+                               if (IoAdapter->RBuffer.length != MLength) {
+                                       this->complete = 0;
+                               } else {
+                                       this->complete = 1;
+                               }
+                               memcpy(IoAdapter->RBuffer.P, cma, IoAdapter->RBuffer.length);
+                               this->RBuffer = (DBUFFER *)&IoAdapter->RBuffer;
+                       }
+#endif
+                       if (!cma) {
+                               a->ram_look_ahead(a, RBuffer, this);
+                       }
+                       this->RNum = 0;
+                       CALLBACK(a, this);
+                       /* map entity ptr, selector could be re-mapped by call to   */
+                       /* IDI from within callback                                 */
+                       this = entity_ptr(a, a->IdTable[Id]);
+                       xdi_xlog_ind(XDI_A_NR(a), Id, Ch, Ind,
+                                    1/* rnr_valid */, this->RNR/* rnr */, a->IdTypeTable[this->No]);
+                       /* check for RNR                                            */
+                       if (this->RNR == 1) {
+                               this->RNR = 0;
+                               return 1;
+                       }
+                       /* if no buffers are provided by the application, the       */
+                       /* application want to copy the data itself including       */
+                       /* N_MDATA/LL_MDATA chaining                                */
+                       if (!this->RNR && !this->RNum) {
+                               xdi_xlog_ind(XDI_A_NR(a), Id, Ch, Ind,
+                                            2/* rnr_valid */, 0/* rnr */, a->IdTypeTable[this->No]);
+                               return 0;
+                       }
+                       /* if there is no RNR, set the More flag                    */
+                       this->RCurrent = 0;
+                       this->ROffset = 0;
+               }
+               if (this->RNR == 2) {
+                       if (Ind != this->MInd) {
+                               this->RCurrent = 0xff;
+                               this->RNR = 0;
+                       }
+                       return 0;
+               }
+               /* if we have received buffers from the application, copy   */
+               /* the data into these buffers                              */
+               offset = 0;
+               R = PTR_R(a, this);
+               do {
+                       if (this->ROffset == R[this->RCurrent].PLength) {
+                               this->ROffset = 0;
+                               this->RCurrent++;
+                       }
+                       if (cma) {
+                               clength = min(MLength, (word)(R[this->RCurrent].PLength-this->ROffset));
+                       } else {
+                               clength = min(a->ram_inw(a, &RBuffer->length)-offset,
+                                             R[this->RCurrent].PLength-this->ROffset);
+                       }
+                       if (R[this->RCurrent].P) {
+                               if (cma) {
+                                       memcpy(PTR_P(a, this, &R[this->RCurrent].P[this->ROffset]),
+                                              &cma[offset],
+                                              clength);
+                               } else {
+                                       a->ram_in_buffer(a,
+                                                        &RBuffer->P[offset],
+                                                        PTR_P(a, this, &R[this->RCurrent].P[this->ROffset]),
+                                                        clength);
+                               }
+                       }
+                       offset += clength;
+                       this->ROffset += clength;
+                       if (cma) {
+                               if (offset >= MLength) {
+                                       break;
+                               }
+                               continue;
+                       }
+               } while (offset < (a->ram_inw(a, &RBuffer->length)));
+               /* if it's the last buffer of the packet, call the          */
+               /* application callback function for the receive complete   */
+               /* call                                                     */
+               if (Ind != this->MInd) {
+                       R[this->RCurrent].PLength = this->ROffset;
+                       if (this->ROffset) this->RCurrent++;
+                       this->RNum = this->RCurrent;
+                       this->RCurrent = 0xff;
+                       this->Ind = Ind;
+                       this->complete = 2;
+                       xdi_xlog_ind(XDI_A_NR(a), Id, Ch, Ind,
+                                    3/* rnr_valid */, 0/* rnr */, a->IdTypeTable[this->No]);
+                       CALLBACK(a, this);
+               }
+               return 0;
+       }
+       return 2;
+}
+#if defined(XDI_USE_XLOG)
+/* -----------------------------------------------------------
+   This function works in the same way as xlog on the
+   active board
+   ----------------------------------------------------------- */
+static void xdi_xlog(byte *msg, word code, int length) {
+       xdi_dbg_xlog("\x00\x02", msg, code, length);
+}
+#endif
+/* -----------------------------------------------------------
+   This function writes the information about the Return Code
+   processing in the trace buffer. Trace ID is 221.
+   INPUT:
+   Adapter - system unicue adapter number (0 ... 255)
+   Id      - Id of the entity that had sent this return code
+   Ch      - Channel of the entity that had sent this return code
+   Rc      - return code value
+   cb:       (0...2)
+   switch (cb) {
+   case 0: printf ("DELIVERY"); break;
+   case 1: printf ("CALLBACK"); break;
+   case 2: printf ("ASSIGN"); break;
+   }
+   DELIVERY - have entered isdn_rc with this RC
+   CALLBACK - about to make callback to the application
+   for this RC
+   ASSIGN   - about to make callback for RC that is result
+   of ASSIGN request. It is no DELIVERY message
+   before of this message
+   type   - the Id that was sent by the ASSIGN of this entity.
+   This should be global Id like NL_ID, DSIG_ID, MAN_ID.
+   An unknown Id will cause "?-" in the front of the request.
+   In this case the log.c is to be extended.
+   ----------------------------------------------------------- */
+static void xdi_xlog_rc_event(byte Adapter,
+                             byte Id, byte Ch, byte Rc, byte cb, byte type) {
+#if defined(XDI_USE_XLOG)
+       word LogInfo[4];
+       PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8)));
+       PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8)));
+       PUT_WORD(&LogInfo[2], ((word)Rc | (word)(type << 8)));
+       PUT_WORD(&LogInfo[3], cb);
+       xdi_xlog((byte *)&LogInfo[0], 221, sizeof(LogInfo));
+#endif
+}
+/* ------------------------------------------------------------------------
+   This function writes the information about the request processing
+   in the trace buffer. Trace ID is 220.
+   INPUT:
+   Adapter - system unicue adapter number (0 ... 255)
+   Id      - Id of the entity that had sent this request
+   Ch      - Channel of the entity that had sent this request
+   Req     - Code of the request
+   type    - the Id that was sent by the ASSIGN of this entity.
+   This should be global Id like NL_ID, DSIG_ID, MAN_ID.
+   An unknown Id will cause "?-" in the front of the request.
+   In this case the log.c is to be extended.
+   ------------------------------------------------------------------------ */
+static void xdi_xlog_request(byte Adapter, byte Id,
+                            byte Ch, byte Req, byte type) {
+#if defined(XDI_USE_XLOG)
+       word LogInfo[3];
+       PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8)));
+       PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8)));
+       PUT_WORD(&LogInfo[2], ((word)Req | (word)(type << 8)));
+       xdi_xlog((byte *)&LogInfo[0], 220, sizeof(LogInfo));
+#endif
+}
+/* ------------------------------------------------------------------------
+   This function writes the information about the indication processing
+   in the trace buffer. Trace ID is 222.
+   INPUT:
+   Adapter - system unicue adapter number (0 ... 255)
+   Id      - Id of the entity that had sent this indication
+   Ch      - Channel of the entity that had sent this indication
+   Ind     - Code of the indication
+   rnr_valid: (0 .. 3) supported
+   switch (rnr_valid) {
+   case 0: printf ("DELIVERY"); break;
+   case 1: printf ("RNR=%d", rnr);
+   case 2: printf ("RNum=0");
+   case 3: printf ("COMPLETE");
+   }
+   DELIVERY - indication entered isdn_rc function
+   RNR=...  - application had returned RNR=... after the
+   look ahead callback
+   RNum=0   - application had not returned any buffer to copy
+   this indication and will copy it self
+   COMPLETE - XDI had copied the data to the buffers provided
+   bu the application and is about to issue the
+   final callback
+   rnr:  Look case 1 of the rnr_valid
+   type: the Id that was sent by the ASSIGN of this entity. This should
+   be global Id like NL_ID, DSIG_ID, MAN_ID. An unknown Id will
+   cause "?-" in the front of the request. In this case the
+   log.c is to be extended.
+   ------------------------------------------------------------------------ */
+static void xdi_xlog_ind(byte Adapter,
+                        byte Id,
+                        byte Ch,
+                        byte Ind,
+                        byte rnr_valid,
+                        byte rnr,
+                        byte type) {
+#if defined(XDI_USE_XLOG)
+       word LogInfo[4];
+       PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8)));
+       PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8)));
+       PUT_WORD(&LogInfo[2], ((word)Ind | (word)(type << 8)));
+       PUT_WORD(&LogInfo[3], ((word)rnr | (word)(rnr_valid << 8)));
+       xdi_xlog((byte *)&LogInfo[0], 222, sizeof(LogInfo));
+#endif
+}