linux/drivers/isdn/hardware/eicon/di.c
<<
>>
Prefs
   1
   2/*
   3 *
   4  Copyright (c) Eicon Networks, 2002.
   5 *
   6  This source file is supplied for the use with
   7  Eicon Networks range of DIVA Server Adapters.
   8 *
   9  Eicon File Revision :    2.1
  10 *
  11  This program is free software; you can redistribute it and/or modify
  12  it under the terms of the GNU General Public License as published by
  13  the Free Software Foundation; either version 2, or (at your option)
  14  any later version.
  15 *
  16  This program is distributed in the hope that it will be useful,
  17  but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
  18  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  19  See the GNU General Public License for more details.
  20 *
  21  You should have received a copy of the GNU General Public License
  22  along with this program; if not, write to the Free Software
  23  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24 *
  25 */
  26#include "platform.h"
  27#include "pc.h"
  28#include "pr_pc.h"
  29#include "di_defs.h"
  30#include "di.h"
  31#if !defined USE_EXTENDED_DEBUGS
  32  #include "dimaint.h"
  33#else
  34  #define dprintf
  35#endif
  36#include "io.h"
  37#include "dfifo.h"
  38#define PR_RAM  ((struct pr_ram *)0)
  39#define RAM ((struct dual *)0)
  40/*------------------------------------------------------------------*/
  41/* local function prototypes                                        */
  42/*------------------------------------------------------------------*/
  43void pr_out(ADAPTER * a);
  44byte pr_dpc(ADAPTER * a);
  45static byte pr_ready(ADAPTER * a);
  46static byte isdn_rc(ADAPTER *, byte, byte, byte, word, dword, dword);
  47static byte isdn_ind(ADAPTER *, byte, byte, byte, PBUFFER *, byte, word);
  48/* -----------------------------------------------------------------
  49    Functions used for the extended XDI Debug
  50    macros
  51    global convergence counter (used by all adapters)
  52    Look by the implementation part of the functions
  53    about the parameters.
  54    If you change the dubugging parameters, then you should update
  55    the aididbg.doc in the IDI doc's.
  56   ----------------------------------------------------------------- */
  57#if defined(XDI_USE_XLOG)
  58#define XDI_A_NR(_x_) ((byte)(((ISDN_ADAPTER *)(_x_->io))->ANum))
  59static void xdi_xlog (byte *msg, word code, int length);
  60static byte xdi_xlog_sec = 0;
  61#else
  62#define XDI_A_NR(_x_) ((byte)0)
  63#endif
  64static void xdi_xlog_rc_event (byte Adapter,
  65                               byte Id, byte Ch, byte Rc, byte cb, byte type);
  66static void xdi_xlog_request (byte Adapter, byte Id,
  67                              byte Ch, byte Req, byte type);
  68static void xdi_xlog_ind (byte Adapter,
  69                          byte Id,
  70                          byte Ch,
  71                          byte Ind,
  72                          byte rnr_valid,
  73                          byte rnr,
  74                          byte type);
  75/*------------------------------------------------------------------*/
  76/* output function                                                  */
  77/*------------------------------------------------------------------*/
  78void pr_out(ADAPTER * a)
  79{
  80  byte e_no;
  81  ENTITY  * this = NULL;
  82  BUFFERS  *X;
  83  word length;
  84  word i;
  85  word clength;
  86  REQ * ReqOut;
  87  byte more;
  88  byte ReadyCount;
  89  byte ReqCount;
  90  byte Id;
  91  dtrc(dprintf("pr_out"));
  92        /* while a request is pending ...                           */
  93  e_no = look_req(a);
  94  if(!e_no)
  95  {
  96    dtrc(dprintf("no_req"));
  97    return;
  98  }
  99  ReadyCount = pr_ready(a);
 100  if(!ReadyCount)
 101  {
 102    dtrc(dprintf("not_ready"));
 103    return;
 104  }
 105  ReqCount = 0;
 106  while(e_no && ReadyCount) {
 107    next_req(a);
 108    this = entity_ptr(a, e_no);
 109#ifdef USE_EXTENDED_DEBUGS
 110    if ( !this )
 111    {
 112      DBG_FTL(("XDI: [%02x] !A%d ==> NULL entity ptr - try to ignore",
 113               xdi_xlog_sec++, (int)((ISDN_ADAPTER *)a->io)->ANum))
 114      e_no = look_req(a) ;
 115      ReadyCount-- ;
 116      continue ;
 117    }
 118    {
 119      DBG_TRC((">A%d Id=0x%x Req=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, this->Id, this->Req))
 120    }
 121#else
 122    dbug(dprintf("out:Req=%x,Id=%x,Ch=%x",this->Req,this->Id,this->ReqCh));
 123#endif
 124        /* get address of next available request buffer             */
 125    ReqOut = (REQ *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextReq)];
 126#if defined(DIVA_ISTREAM)
 127    if (!(a->tx_stream[this->Id]   &&
 128        this->Req == N_DATA)) {
 129#endif
 130        /* now copy the data from the current data buffer into the  */
 131        /* adapters request buffer                                  */
 132    length = 0;
 133    i = this->XCurrent;
 134    X = PTR_X(a,this);
 135    while(i<this->XNum && length<270) {
 136      clength = min((word)(270-length),(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}
 239static byte pr_ready(ADAPTER * a)
 240{
 241  byte ReadyCount;
 242  ReadyCount = (byte)(a->ram_in(a, &PR_RAM->ReqOutput) -
 243                      a->ram_in(a, &PR_RAM->ReqInput));
 244  if(!ReadyCount) {
 245    if(!a->ReadyInt) {
 246      a->ram_inc(a, &PR_RAM->ReadyInt);
 247      a->ReadyInt++;
 248    }
 249  }
 250  return ReadyCount;
 251}
 252/*------------------------------------------------------------------*/
 253/* isdn interrupt handler                                           */
 254/*------------------------------------------------------------------*/
 255byte pr_dpc(ADAPTER * a)
 256{
 257  byte Count;
 258  RC * RcIn;
 259  IND * IndIn;
 260  byte c;
 261  byte RNRId;
 262  byte Rc;
 263  byte Ind;
 264        /* if return codes are available ...                        */
 265  if((Count = a->ram_in(a, &PR_RAM->RcOutput)) != 0) {
 266    dtrc(dprintf("#Rc=%x",Count));
 267        /* get the buffer address of the first return code          */
 268    RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextRc)];
 269        /* for all return codes do ...                              */
 270    while(Count--) {
 271      if((Rc=a->ram_in(a, &RcIn->Rc)) != 0) {
 272        dword tmp[2];
 273        /*
 274          Get extended information, associated with return code
 275          */
 276        a->ram_in_buffer(a,
 277                         &RcIn->Reserved2[0],
 278                         (byte*)&tmp[0],
 279                         8);
 280        /* call return code handler, if it is not our return code   */
 281        /* the handler returns 2                                    */
 282        /* for all return codes we process, we clear the Rc field   */
 283        isdn_rc(a,
 284                Rc,
 285                a->ram_in(a, &RcIn->RcId),
 286                a->ram_in(a, &RcIn->RcCh),
 287                a->ram_inw(a, &RcIn->Reference),
 288                tmp[0],  /* type of extended 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}
 345byte scom_test_int(ADAPTER * a)
 346{
 347  return a->ram_in(a,(void *)0x3fe);
 348}
 349void scom_clear_int(ADAPTER * a)
 350{
 351  a->ram_out(a,(void *)0x3fe,0);
 352}
 353/*------------------------------------------------------------------*/
 354/* return code handler                                              */
 355/*------------------------------------------------------------------*/
 356static 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/*------------------------------------------------------------------*/
 558static 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   ----------------------------------------------------------- */
 728static void xdi_xlog (byte *msg, word code, int length) {
 729  xdi_dbg_xlog ("\x00\x02", msg, code, length);
 730}
 731#endif
 732/* -----------------------------------------------------------
 733    This function writes the information about the Return Code
 734    processing in the trace buffer. Trace ID is 221.
 735    INPUT:
 736        Adapter - system unicue adapter number (0 ... 255)
 737        Id      - Id of the entity that had sent this return code
 738        Ch      - Channel of the entity that had sent this return code
 739        Rc      - return code value
 740        cb:       (0...2)
 741                  switch (cb) {
 742                   case 0: printf ("DELIVERY"); break;
 743                   case 1: printf ("CALLBACK"); break;
 744                   case 2: printf ("ASSIGN"); break;
 745                  }
 746                  DELIVERY - have entered isdn_rc with this RC
 747                  CALLBACK - about to make callback to the application
 748                             for this RC
 749                  ASSIGN   - about to make callback for RC that is result
 750                             of ASSIGN request. It is no DELIVERY message
 751                             before of this message
 752        type   - the Id that was sent by the ASSIGN of this entity.
 753                 This should be global Id like NL_ID, DSIG_ID, MAN_ID.
 754                 An unknown Id will cause "?-" in the front of the request.
 755                 In this case the log.c is to be extended.
 756   ----------------------------------------------------------- */
 757static void xdi_xlog_rc_event (byte Adapter,
 758                               byte Id, byte Ch, byte Rc, byte cb, byte type) {
 759#if defined(XDI_USE_XLOG)
 760  word LogInfo[4];
 761  PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8)));
 762  PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8)));
 763  PUT_WORD(&LogInfo[2], ((word)Rc | (word)(type << 8)));
 764  PUT_WORD(&LogInfo[3], cb);
 765  xdi_xlog ((byte*)&LogInfo[0], 221, sizeof(LogInfo));
 766#endif
 767}
 768/* ------------------------------------------------------------------------
 769    This function writes the information about the request processing
 770    in the trace buffer. Trace ID is 220.
 771    INPUT:
 772        Adapter - system unicue adapter number (0 ... 255)
 773        Id      - Id of the entity that had sent this request
 774        Ch      - Channel of the entity that had sent this request
 775        Req     - Code of the request
 776        type    - the Id that was sent by the ASSIGN of this entity.
 777                  This should be global Id like NL_ID, DSIG_ID, MAN_ID.
 778                  An unknown Id will cause "?-" in the front of the request.
 779                  In this case the log.c is to be extended.
 780   ------------------------------------------------------------------------ */
 781static void xdi_xlog_request (byte Adapter, byte Id,
 782                              byte Ch, byte Req, byte type) {
 783#if defined(XDI_USE_XLOG)
 784  word LogInfo[3];
 785  PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8)));
 786  PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8)));
 787  PUT_WORD(&LogInfo[2], ((word)Req | (word)(type << 8)));
 788  xdi_xlog ((byte*)&LogInfo[0], 220, sizeof(LogInfo));
 789#endif
 790}
 791/* ------------------------------------------------------------------------
 792    This function writes the information about the indication processing
 793    in the trace buffer. Trace ID is 222.
 794    INPUT:
 795        Adapter - system unicue adapter number (0 ... 255)
 796        Id      - Id of the entity that had sent this indication
 797        Ch      - Channel of the entity that had sent this indication
 798        Ind     - Code of the indication
 799        rnr_valid: (0 .. 3) supported
 800          switch (rnr_valid) {
 801            case 0: printf ("DELIVERY"); break;
 802            case 1: printf ("RNR=%d", rnr);
 803            case 2: printf ("RNum=0");
 804            case 3: printf ("COMPLETE");
 805          }
 806          DELIVERY - indication entered isdn_rc function
 807          RNR=...  - application had returned RNR=... after the
 808                     look ahead callback
 809          RNum=0   - 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   ------------------------------------------------------------------------ */
 820static void xdi_xlog_ind (byte Adapter,
 821                          byte Id,
 822                          byte Ch,
 823                          byte Ind,
 824                          byte rnr_valid,
 825                          byte rnr,
 826                          byte type) {
 827#if defined(XDI_USE_XLOG)
 828  word LogInfo[4];
 829  PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8)));
 830  PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8)));
 831  PUT_WORD(&LogInfo[2], ((word)Ind | (word)(type << 8)));
 832  PUT_WORD(&LogInfo[3], ((word)rnr | (word)(rnr_valid << 8)));
 833  xdi_xlog ((byte*)&LogInfo[0], 222, sizeof(LogInfo));
 834#endif
 835}
 836