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