Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[linux/fpc-iii.git] / drivers / isdn / hardware / eicon / di.c
blobcd3fba1add12d1ff8b867d4037d6395e79d08b7d
2 /*
4 Copyright (c) Eicon Networks, 2002.
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
9 Eicon File Revision : 2.1
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.
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.
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.
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 /*------------------------------------------------------------------*/
43 void pr_out(ADAPTER *a);
44 byte pr_dpc(ADAPTER *a);
45 static byte pr_ready(ADAPTER *a);
46 static byte isdn_rc(ADAPTER *, byte, byte, byte, word, dword, dword);
47 static 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))
59 static void xdi_xlog(byte *msg, word code, int length);
60 static byte xdi_xlog_sec = 0;
61 #else
62 #define XDI_A_NR(_x_) ((byte)0)
63 #endif
64 static void xdi_xlog_rc_event(byte Adapter,
65 byte Id, byte Ch, byte Rc, byte cb, byte type);
66 static void xdi_xlog_request(byte Adapter, byte Id,
67 byte Ch, byte Req, byte type);
68 static 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 /*------------------------------------------------------------------*/
78 void pr_out(ADAPTER *a)
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)
96 dtrc(dprintf("no_req"));
97 return;
99 ReadyCount = pr_ready(a);
100 if (!ReadyCount)
102 dtrc(dprintf("not_ready"));
103 return;
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)
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;
119 DBG_TRC((">A%d Id=0x%x Req=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, this->Id, this->Req))
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;
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;
161 length = 0;
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;
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;
187 Note that remove request was sent to the card
189 if (this->Req == REMOVE) {
190 a->misc_flags_table[e_no] |= DIVA_MISC_FLAGS_REMOVE_PENDING;
193 /* if we did chaining, this entity is put back into the */
194 /* request queue */
195 if (more) {
196 req_queue(a, this->No);
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));
216 a->ram_outw(a, &PR_RAM->NextReq, a->ram_inw(a, &ReqOut->next));
217 ReadyCount--;
218 ReqCount++;
219 e_no = look_req(a);
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++)
232 if (a->FlowControlIdTable[i] == Id)
233 a->FlowControlIdTable[i] = 0;
235 a->IdTable[Id] = 0;
236 this->Id = 0;
239 static byte pr_ready(ADAPTER *a)
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++;
250 return ReadyCount;
252 /*------------------------------------------------------------------*/
253 /* isdn interrupt handler */
254 /*------------------------------------------------------------------*/
255 byte pr_dpc(ADAPTER *a)
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];
274 Get extended information, associated with return code
276 a->ram_in_buffer(a,
277 &RcIn->Reserved2[0],
278 (byte *)&tmp[0],
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,
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);
292 /* get buffer address of next return code */
293 RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &RcIn->next)];
295 /* clear all return codes (no chaining!) */
296 a->ram_out(a, &PR_RAM->RcOutput, 0);
297 /* call output function */
298 pr_out(a);
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);
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);
338 /* get buffer address of next indication */
339 IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &IndIn->next)];
341 a->ram_out(a, &PR_RAM->IndOutput, 0);
343 return false;
345 byte scom_test_int(ADAPTER *a)
347 return a->ram_in(a, (void *)0x3fe);
349 void scom_clear_int(ADAPTER *a)
351 a->ram_out(a, (void *)0x3fe, 0);
353 /*------------------------------------------------------------------*/
354 /* return code handler */
355 /*------------------------------------------------------------------*/
356 static 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)
364 ENTITY *this;
365 byte e_no;
366 word i;
367 int cancel_rc;
368 #ifdef USE_EXTENDED_DEBUGS
370 DBG_TRC(("<A%d Id=0x%x Rc=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, Id, Rc))
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;
382 return 2;
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);
401 if (extended_info_type == DIVA_RC_TYPE_REMOVE_COMPLETE)
402 a->RcExtensionSupported = true;
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++)
409 if (a->FlowControlIdTable[i] == Id)
410 a->FlowControlIdTable[i] = 0;
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));
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;
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.
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;
459 cancel_rc = !(a->misc_flags_table[e_no] & DIVA_MISC_FLAGS_NO_RC_CANCELLING);
460 if (cancel_rc && (a->FlowControlIdTable[Ch] == Id))
462 a->FlowControlIdTable[Ch] = 0;
463 if ((Rc != OK) || !a->FlowControlSkipTable[Ch])
465 this->Rc = Rc;
466 if (Ch == this->ReqCh)
468 this->More &= ~(XBUSY | XMOREC);
469 this->complete = 0xff;
471 xdi_xlog_rc_event(XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
472 CALLBACK(a, this);
474 return 0;
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);
486 return 0;
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;
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;
534 #endif /* } */
535 CALLBACK(a, this);
536 if (Rc == ASSIGN_OK) {
537 a->IdTable[Id] = e_no;
539 else
541 free_entity(a, e_no);
542 for (i = 0; i < 256; i++)
544 if (a->FlowControlIdTable[i] == Id)
545 a->FlowControlIdTable[i] = 0;
547 a->IdTable[Id] = 0;
548 this->Id = 0;
550 return 1;
553 return 2;
555 /*------------------------------------------------------------------*/
556 /* indication handler */
557 /*------------------------------------------------------------------*/
558 static byte isdn_ind(ADAPTER *a,
559 byte Ind,
560 byte Id,
561 byte Ch,
562 PBUFFER *RBuffer,
563 byte MInd,
564 word MLength)
566 ENTITY *this;
567 word clength;
568 word offset;
569 BUFFERS *R;
570 byte *cma = NULL;
571 #ifdef USE_EXTENDED_DEBUGS
573 DBG_TRC(("<A%d Id=0x%x Ind=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, Id, Ind))
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;
591 else {
592 this->complete = 1;
593 this->Ind = Ind;
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,
621 cma,
622 sizeof(a->stream_buffer),
623 &final, NULL, NULL);
625 IoAdapter->RBuffer.length = min(MLength, (word)270);
626 if (IoAdapter->RBuffer.length != MLength) {
627 this->complete = 0;
628 } else {
629 this->complete = 1;
631 memcpy(IoAdapter->RBuffer.P, cma, IoAdapter->RBuffer.length);
632 this->RBuffer = (DBUFFER *)&IoAdapter->RBuffer;
634 #endif
635 if (!cma) {
636 a->ram_look_ahead(a, RBuffer, this);
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;
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;
658 /* if there is no RNR, set the More flag */
659 this->RCurrent = 0;
660 this->ROffset = 0;
662 if (this->RNR == 2) {
663 if (Ind != this->MInd) {
664 this->RCurrent = 0xff;
665 this->RNR = 0;
667 return 0;
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++;
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);
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);
696 offset += clength;
697 this->ROffset += clength;
698 if (cma) {
699 if (offset >= MLength) {
700 break;
702 continue;
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);
719 return 0;
721 return 2;
723 #if defined(XDI_USE_XLOG)
724 /* -----------------------------------------------------------
725 This function works in the same way as xlog on the
726 active board
727 ----------------------------------------------------------- */
728 static void xdi_xlog(byte *msg, word code, int length) {
729 xdi_dbg_xlog("\x00\x02", msg, code, length);
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;
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 ----------------------------------------------------------- */
757 static 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
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 ------------------------------------------------------------------------ */
781 static 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
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");
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 ------------------------------------------------------------------------ */
820 static 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