diff options
Diffstat (limited to 'drivers/isdn/hardware/eicon/di.c')
-rw-r--r-- | drivers/isdn/hardware/eicon/di.c | 835 |
1 files changed, 835 insertions, 0 deletions
diff --git a/drivers/isdn/hardware/eicon/di.c b/drivers/isdn/hardware/eicon/di.c new file mode 100644 index 000000000..cd3fba1ad --- /dev/null +++ b/drivers/isdn/hardware/eicon/di.c @@ -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 +} |