Merge Christoph's freeze cleanup patch
[linux-2.6] / drivers / isdn / hardware / eicon / di.c
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 /*------------------------------------------------------------------*/
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)
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),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 }
239 static 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 /*------------------------------------------------------------------*/
255 byte 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 informtion */
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 }
345 byte scom_test_int(ADAPTER * a)
346 {
347   return a->ram_in(a,(void *)0x3fe);
348 }
349 void scom_clear_int(ADAPTER * a)
350 {
351   a->ram_out(a,(void *)0x3fe,0);
352 }
353 /*------------------------------------------------------------------*/
354 /* return code handler                                              */
355 /*------------------------------------------------------------------*/
356 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 /*------------------------------------------------------------------*/
558 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, 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, 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    ----------------------------------------------------------- */
728 static 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    ----------------------------------------------------------- */
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
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    ------------------------------------------------------------------------ */
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
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   - aplication 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
835 }