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