| |
| /* |
| * |
| 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 - aplication 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 |
| } |