ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / 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 void scom_out(ADAPTER * a);
46 byte scom_dpc(ADAPTER * a);
47 static byte pr_ready(ADAPTER * a);
48 static byte scom_ready(ADAPTER * a);
49 static byte isdn_rc(ADAPTER *, byte, byte, byte, word, dword, dword);
50 static byte isdn_ind(ADAPTER *, byte, byte, byte, PBUFFER *, byte, word);
51 /* -----------------------------------------------------------------
52     Functions used for the extended XDI Debug
53     macros
54     global convergence counter (used by all adapters)
55     Look by the implementation part of the functions
56     about the parameters.
57     If you change the dubugging parameters, then you should update
58     the aididbg.doc in the IDI doc's.
59    ----------------------------------------------------------------- */
60 #if defined(XDI_USE_XLOG)
61 #define XDI_A_NR(_x_) ((byte)(((ISDN_ADAPTER *)(_x_->io))->ANum))
62 #else
63 #define XDI_A_NR(_x_) ((byte)0)
64 #endif
65 byte xdi_xlog_sec = 0;
66 void xdi_xlog (byte *msg, word code, int length);
67 static void xdi_xlog_rc_event (byte Adapter,
68                                byte Id, byte Ch, byte Rc, byte cb, byte type);
69 static void xdi_xlog_request (byte Adapter, byte Id,
70                               byte Ch, byte Req, byte type);
71 static void xdi_xlog_ind (byte Adapter,
72                           byte Id,
73                           byte Ch,
74                           byte Ind,
75                           byte rnr_valid,
76                           byte rnr,
77                           byte type);
78 /*------------------------------------------------------------------*/
79 /* output function                                                  */
80 /*------------------------------------------------------------------*/
81 void pr_out(ADAPTER * a)
82 {
83   byte e_no;
84   ENTITY  * this = 0;
85   BUFFERS  *X;
86   word length;
87   word i;
88   word clength;
89   REQ * ReqOut;
90   byte more;
91   byte ReadyCount;
92   byte ReqCount;
93   byte Id;
94   dtrc(dprintf("pr_out"));
95         /* while a request is pending ...                           */
96   e_no = look_req(a);
97   if(!e_no)
98   {
99     dtrc(dprintf("no_req"));
100     return;
101   }
102   ReadyCount = pr_ready(a);
103   if(!ReadyCount)
104   {
105     dtrc(dprintf("not_ready"));
106     return;
107   }
108   ReqCount = 0;
109   while(e_no && ReadyCount) {
110     next_req(a);
111     this = entity_ptr(a, e_no);
112 #ifdef USE_EXTENDED_DEBUGS
113     if ( !this )
114     {
115       DBG_FTL(("XDI: [%02x] !A%d ==> NULL entity ptr - try to ignore",
116                xdi_xlog_sec++, (int)((ISDN_ADAPTER *)a->io)->ANum))
117       e_no = look_req(a) ;
118       ReadyCount-- ;
119       continue ;
120     }
121     {
122       DBG_TRC((">A%d Id=0x%x Req=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, this->Id, this->Req))
123     }
124 #else
125     dbug(dprintf("out:Req=%x,Id=%x,Ch=%x",this->Req,this->Id,this->ReqCh));
126 #endif
127         /* get address of next available request buffer             */
128     ReqOut = (REQ *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextReq)];
129 #if defined(DIVA_ISTREAM)
130     if (!(a->tx_stream[this->Id]   &&
131         this->Req == N_DATA)) {
132 #endif
133         /* now copy the data from the current data buffer into the  */
134         /* adapters request buffer                                  */
135     length = 0;
136     i = this->XCurrent;
137     X = PTR_X(a,this);
138     while(i<this->XNum && length<270) {
139       clength = MIN((word)(270-length),X[i].PLength-this->XOffset);
140       a->ram_out_buffer(a,
141                         &ReqOut->XBuffer.P[length],
142                         PTR_P(a,this,&X[i].P[this->XOffset]),
143                         clength);
144       length +=clength;
145       this->XOffset +=clength;
146       if(this->XOffset==X[i].PLength) {
147         this->XCurrent = (byte)++i;
148         this->XOffset = 0;
149       }
150     }
151 #if defined(DIVA_ISTREAM)
152    } else { /* Use CMA extension in order to transfer data to the card */
153       i = this->XCurrent;
154       X = PTR_X(a,this);
155       while (i < this->XNum) {
156         diva_istream_write (a,
157                             this->Id,
158                             PTR_P(a,this,&X[i].P[0]),
159                             X[i].PLength,
160                             ((i+1) == this->XNum),
161                             0, 0);
162         this->XCurrent = (byte)++i;
163       }
164       length = 0;
165    }
166 #endif
167     a->ram_outw(a, &ReqOut->XBuffer.length, length);
168     a->ram_out(a, &ReqOut->ReqId, this->Id);
169     a->ram_out(a, &ReqOut->ReqCh, this->ReqCh);
170         /* if it's a specific request (no ASSIGN) ...                */
171     if(this->Id &0x1f) {
172         /* if buffers are left in the list of data buffers do       */
173         /* do chaining (LL_MDATA, N_MDATA)                          */
174       this->More++;
175       if(i<this->XNum && this->MInd) {
176         xdi_xlog_request (XDI_A_NR(a), this->Id, this->ReqCh, this->MInd,
177                           a->IdTypeTable[this->No]);
178         a->ram_out(a, &ReqOut->Req, this->MInd);
179         more = TRUE;
180       }
181       else {
182         xdi_xlog_request (XDI_A_NR(a), this->Id, this->ReqCh, this->Req,
183                           a->IdTypeTable[this->No]);
184         this->More |=XMOREF;
185         a->ram_out(a, &ReqOut->Req, this->Req);
186         more = FALSE;
187         if (a->FlowControlIdTable[this->ReqCh] == this->Id)
188           a->FlowControlSkipTable[this->ReqCh] = TRUE;
189         /*
190            Note that remove request was sent to the card
191            */
192         if (this->Req == REMOVE) {
193           a->misc_flags_table[e_no] |= DIVA_MISC_FLAGS_REMOVE_PENDING;
194         }
195       }
196         /* if we did chaining, this entity is put back into the     */
197         /* request queue                                            */
198       if(more) {
199         req_queue(a,this->No);
200       }
201     }
202         /* else it's a ASSIGN                                       */
203     else {
204         /* save the request code used for buffer chaining           */
205       this->MInd = 0;
206       if (this->Id==BLLC_ID) this->MInd = LL_MDATA;
207       if (this->Id==NL_ID   ||
208           this->Id==TASK_ID ||
209           this->Id==MAN_ID
210         ) this->MInd = N_MDATA;
211         /* send the ASSIGN                                          */
212       a->IdTypeTable[this->No] = this->Id;
213       xdi_xlog_request (XDI_A_NR(a),this->Id,this->ReqCh,this->Req, this->Id);
214       this->More |=XMOREF;
215       a->ram_out(a, &ReqOut->Req, this->Req);
216         /* save the reference of the ASSIGN                         */
217       assign_queue(a, this->No, a->ram_inw(a, &ReqOut->Reference));
218     }
219     a->ram_outw(a, &PR_RAM->NextReq, a->ram_inw(a, &ReqOut->next));
220     ReadyCount--;
221     ReqCount++;
222     e_no = look_req(a);
223   }
224         /* send the filled request buffers to the ISDN adapter      */
225   a->ram_out(a, &PR_RAM->ReqInput,
226              (byte)(a->ram_in(a, &PR_RAM->ReqInput) + ReqCount));
227         /* if it is a 'unreturncoded' UREMOVE request, remove the  */
228         /* Id from our table after sending the request             */
229   if(this && (this->Req==UREMOVE) && this->Id) {
230     Id = this->Id;
231     e_no = a->IdTable[Id];
232     free_entity(a, e_no);
233     for (i = 0; i < 256; i++)
234     {
235       if (a->FlowControlIdTable[i] == Id)
236         a->FlowControlIdTable[i] = 0;
237     }
238     a->IdTable[Id] = 0;
239     this->Id = 0;
240   }
241 }
242 static byte pr_ready(ADAPTER * a)
243 {
244   byte ReadyCount;
245   ReadyCount = (byte)(a->ram_in(a, &PR_RAM->ReqOutput) -
246                       a->ram_in(a, &PR_RAM->ReqInput));
247   if(!ReadyCount) {
248     if(!a->ReadyInt) {
249       a->ram_inc(a, &PR_RAM->ReadyInt);
250       a->ReadyInt++;
251     }
252   }
253   return ReadyCount;
254 }
255 /*------------------------------------------------------------------*/
256 /* isdn interrupt handler                                           */
257 /*------------------------------------------------------------------*/
258 byte pr_dpc(ADAPTER * a)
259 {
260   byte Count;
261   RC * RcIn;
262   IND * IndIn;
263   byte c;
264   byte RNRId;
265   byte Rc;
266   byte Ind;
267         /* if return codes are available ...                        */
268   if((Count = a->ram_in(a, &PR_RAM->RcOutput)) != 0) {
269     dtrc(dprintf("#Rc=%x",Count));
270         /* get the buffer address of the first return code          */
271     RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextRc)];
272         /* for all return codes do ...                              */
273     while(Count--) {
274       if((Rc=a->ram_in(a, &RcIn->Rc)) != 0) {
275         dword tmp[2];
276         /*
277           Get extended information, associated with return code
278           */
279         a->ram_in_buffer(a,
280                          &RcIn->Reserved2[0],
281                          (byte*)&tmp[0],
282                          8);
283         /* call return code handler, if it is not our return code   */
284         /* the handler returns 2                                    */
285         /* for all return codes we process, we clear the Rc field   */
286         isdn_rc(a,
287                 Rc,
288                 a->ram_in(a, &RcIn->RcId),
289                 a->ram_in(a, &RcIn->RcCh),
290                 a->ram_inw(a, &RcIn->Reference),
291                 tmp[0],  /* type of extended informtion */
292                 tmp[1]); /* extended information        */
293         a->ram_out(a, &RcIn->Rc, 0);
294       }
295         /* get buffer address of next return code                   */
296       RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &RcIn->next)];
297     }
298         /* clear all return codes (no chaining!)                    */
299     a->ram_out(a, &PR_RAM->RcOutput ,0);
300         /* call output function                                     */
301     pr_out(a);
302   }
303         /* clear RNR flag                                           */
304   RNRId = 0;
305         /* if indications are available ...                         */
306   if((Count = a->ram_in(a, &PR_RAM->IndOutput)) != 0) {
307     dtrc(dprintf("#Ind=%x",Count));
308         /* get the buffer address of the first indication           */
309     IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextInd)];
310         /* for all indications do ...                               */
311     while(Count--) {
312         /* if the application marks an indication as RNR, all       */
313         /* indications from the same Id delivered in this interrupt */
314         /* are marked RNR                                           */
315       if(RNRId && RNRId==a->ram_in(a, &IndIn->IndId)) {
316         a->ram_out(a, &IndIn->Ind, 0);
317         a->ram_out(a, &IndIn->RNR, TRUE);
318       }
319       else {
320         Ind = a->ram_in(a, &IndIn->Ind);
321         if(Ind) {
322           RNRId = 0;
323         /* call indication handler, a return value of 2 means chain */
324         /* a return value of 1 means RNR                            */
325         /* for all indications we process, we clear the Ind field   */
326           c = isdn_ind(a,
327                        Ind,
328                        a->ram_in(a, &IndIn->IndId),
329                        a->ram_in(a, &IndIn->IndCh),
330                        &IndIn->RBuffer,
331                        a->ram_in(a, &IndIn->MInd),
332                        a->ram_inw(a, &IndIn->MLength));
333           if(c==1) {
334             dtrc(dprintf("RNR"));
335             a->ram_out(a, &IndIn->Ind, 0);
336             RNRId = a->ram_in(a, &IndIn->IndId);
337             a->ram_out(a, &IndIn->RNR, TRUE);
338           }
339         }
340       }
341         /* get buffer address of next indication                    */
342       IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &IndIn->next)];
343     }
344     a->ram_out(a, &PR_RAM->IndOutput, 0);
345   }
346   return FALSE;
347 }
348 byte pr_test_int(ADAPTER * a)
349 {
350   return a->ram_in(a,(void *)0x3ffc);
351 }
352 void pr_clear_int(ADAPTER * a)
353 {
354   a->ram_out(a,(void *)0x3ffc,0);
355 }
356 /*------------------------------------------------------------------*/
357 /* output function                                                  */
358 /*------------------------------------------------------------------*/
359 void scom_out(ADAPTER * a)
360 {
361   byte e_no;
362   ENTITY  * this;
363   BUFFERS  * X;
364   word length;
365   word i;
366   word clength;
367   byte more;
368   byte Id;
369   dtrc(dprintf("scom_out"));
370         /* check if the adapter is ready to accept an request:      */
371   e_no = look_req(a);
372   if(!e_no)
373   {
374     dtrc(dprintf("no_req"));
375     return;
376   }
377   if(!scom_ready(a))
378   {
379     dtrc(dprintf("not_ready"));
380     return;
381   }
382   this = entity_ptr(a,e_no);
383   dtrc(dprintf("out:Req=%x,Id=%x,Ch=%x",this->Req,this->Id,this->ReqCh));
384   next_req(a);
385         /* now copy the data from the current data buffer into the  */
386         /* adapters request buffer                                  */
387   length = 0;
388   i = this->XCurrent;
389   X = PTR_X(a, this);
390   while(i<this->XNum && length<270) {
391     clength = MIN((word)(270-length),X[i].PLength-this->XOffset);
392     a->ram_out_buffer(a,
393                       &RAM->XBuffer.P[length],
394                       PTR_P(a,this,&X[i].P[this->XOffset]),
395                       clength);
396     length +=clength;
397     this->XOffset +=clength;
398     if(this->XOffset==X[i].PLength) {
399       this->XCurrent = (byte)++i;
400       this->XOffset = 0;
401     }
402   }
403   a->ram_outw(a, &RAM->XBuffer.length, length);
404   a->ram_out(a, &RAM->ReqId, this->Id);
405   a->ram_out(a, &RAM->ReqCh, this->ReqCh);
406         /* if it's a specific request (no ASSIGN) ...                */
407   if(this->Id &0x1f) {
408         /* if buffers are left in the list of data buffers do       */
409         /* chaining (LL_MDATA, N_MDATA)                             */
410     this->More++;
411     if(i<this->XNum && this->MInd) {
412       a->ram_out(a, &RAM->Req, this->MInd);
413       more = TRUE;
414     }
415     else {
416       this->More |=XMOREF;
417       a->ram_out(a, &RAM->Req, this->Req);
418       more = FALSE;
419       if (a->FlowControlIdTable[this->ReqCh] == this->Id)
420         a->FlowControlSkipTable[this->ReqCh] = TRUE;
421       /*
422          Note that remove request was sent to the card
423          */
424       if (this->Req == REMOVE) {
425         a->misc_flags_table[e_no] |= DIVA_MISC_FLAGS_REMOVE_PENDING;
426       }
427     }
428     if(more) {
429       req_queue(a,this->No);
430     }
431   }
432         /* else it's a ASSIGN                                       */
433   else {
434         /* save the request code used for buffer chaining           */
435     this->MInd = 0;
436     if (this->Id==BLLC_ID) this->MInd = LL_MDATA;
437     if (this->Id==NL_ID   ||
438         this->Id==TASK_ID ||
439         this->Id==MAN_ID
440       ) this->MInd = N_MDATA;
441         /* send the ASSIGN                                          */
442     this->More |=XMOREF;
443     a->ram_out(a, &RAM->Req, this->Req);
444         /* save the reference of the ASSIGN                         */
445     assign_queue(a, this->No, 0);
446   }
447         /* if it is a 'unreturncoded' UREMOVE request, remove the  */
448         /* Id from our table after sending the request             */
449   if(this->Req==UREMOVE && this->Id) {
450     Id = this->Id;
451     e_no = a->IdTable[Id];
452     free_entity(a, e_no);
453     for (i = 0; i < 256; i++)
454     {
455       if (a->FlowControlIdTable[i] == Id)
456         a->FlowControlIdTable[i] = 0;
457     }
458     a->IdTable[Id] = 0;
459     this->Id = 0;
460   }
461 }
462 static byte scom_ready(ADAPTER * a)
463 {
464   if(a->ram_in(a, &RAM->Req)) {
465     if(!a->ReadyInt) {
466       a->ram_inc(a, &RAM->ReadyInt);
467       a->ReadyInt++;
468     }
469     return 0;
470   }
471   return 1;
472 }
473 /*------------------------------------------------------------------*/
474 /* isdn interrupt handler                                           */
475 /*------------------------------------------------------------------*/
476 byte scom_dpc(ADAPTER * a)
477 {
478   byte c;
479         /* if a return code is available ...                        */
480   if(a->ram_in(a, &RAM->Rc)) {
481         /* call return code handler, if it is not our return code   */
482         /* the handler returns 2, if it's the return code to an     */
483         /* ASSIGN the handler returns 1                             */
484     c = isdn_rc(a,
485                 a->ram_in(a, &RAM->Rc),
486                 a->ram_in(a, &RAM->RcId),
487                 a->ram_in(a, &RAM->RcCh),
488                 0,
489                 /*
490                   Scom Card does not provide extended information
491                   */
492                 0, 0);
493     switch(c) {
494     case 0:
495       a->ram_out(a, &RAM->Rc, 0);
496       break;
497     case 1:
498       a->ram_out(a, &RAM->Req, 0);
499       a->ram_out(a, &RAM->Rc, 0);
500       break;
501     case 2:
502       return TRUE;
503     }
504         /* call output function                                     */
505     scom_out(a);
506   }
507   else {
508         /* if an indications is available ...                       */
509     if(a->ram_in(a, &RAM->Ind)) {
510         /* call indication handler, a return value of 2 means chain */
511         /* a return value of 1 means RNR                            */
512       c = isdn_ind(a,
513                    a->ram_in(a, &RAM->Ind),
514                    a->ram_in(a, &RAM->IndId),
515                    a->ram_in(a, &RAM->IndCh),
516                    &RAM->RBuffer,
517                    a->ram_in(a, &RAM->MInd),
518                    a->ram_inw(a, &RAM->MLength));
519       switch(c) {
520       case 0:
521         a->ram_out(a, &RAM->Ind, 0);
522         break;
523       case 1:
524         dtrc(dprintf("RNR"));
525         a->ram_out(a, &RAM->RNR, TRUE);
526         break;
527       case 2:
528         return TRUE;
529       }
530     }
531   }
532   return FALSE;
533 }
534 byte scom_test_int(ADAPTER * a)
535 {
536   return a->ram_in(a,(void *)0x3fe);
537 }
538 void scom_clear_int(ADAPTER * a)
539 {
540   a->ram_out(a,(void *)0x3fe,0);
541 }
542 void quadro_clear_int(ADAPTER * a)
543 {
544   a->ram_out(a,(void *)0x3fe,0);
545   a->ram_out(a,(void *)0x401,0);
546 }
547 /*------------------------------------------------------------------*/
548 /* return code handler                                              */
549 /*------------------------------------------------------------------*/
550 byte isdn_rc(ADAPTER * a,
551              byte Rc,
552              byte Id,
553              byte Ch,
554              word Ref,
555              dword extended_info_type,
556              dword extended_info)
557 {
558   ENTITY  * this;
559   byte e_no;
560   word i;
561   int cancel_rc;
562 #ifdef USE_EXTENDED_DEBUGS
563   {
564     DBG_TRC(("<A%d Id=0x%x Rc=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, Id, Rc))
565   }
566 #else
567   dbug(dprintf("isdn_rc(Rc=%x,Id=%x,Ch=%x)",Rc,Id,Ch));
568 #endif
569         /* check for ready interrupt                                */
570   if(Rc==READY_INT) {
571     xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 0, 0);
572     if(a->ReadyInt) {
573       a->ReadyInt--;
574       return 0;
575     }
576     return 2;
577   }
578         /* if we know this Id ...                                   */
579   e_no = a->IdTable[Id];
580   if(e_no) {
581     this = entity_ptr(a,e_no);
582     xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 0, a->IdTypeTable[this->No]);
583     this->RcCh = Ch;
584         /* if it is a return code to a REMOVE request, remove the   */
585         /* Id from our table                                        */
586     if ((a->misc_flags_table[e_no] & DIVA_MISC_FLAGS_REMOVE_PENDING) &&
587         (Rc==OK)) {
588       if (a->IdTypeTable[e_no] == NL_ID) {
589         if (a->RcExtensionSupported &&
590             (extended_info_type != DIVA_RC_TYPE_REMOVE_COMPLETE)) {
591         dtrc(dprintf("XDI: N-REMOVE, A(%02x) Id:%02x, ignore RC=OK",
592                         XDI_A_NR(a),Id));
593           return (0);
594         }
595         if (extended_info_type == DIVA_RC_TYPE_REMOVE_COMPLETE)
596           a->RcExtensionSupported = TRUE;
597       }
598       a->misc_flags_table[e_no] &= ~DIVA_MISC_FLAGS_REMOVE_PENDING;
599       a->misc_flags_table[e_no] &= ~DIVA_MISC_FLAGS_NO_RC_CANCELLING;
600       free_entity(a, e_no);
601       for (i = 0; i < 256; i++)
602       {
603         if (a->FlowControlIdTable[i] == Id)
604           a->FlowControlIdTable[i] = 0;
605       }
606       a->IdTable[Id] = 0;
607       this->Id = 0;
608       /* ---------------------------------------------------------------
609         If we send N_DISC or N_DISK_ACK after we have received OK_FC
610         then the card will respond with OK_FC and later with RC==OK.
611         If we send N_REMOVE in this state we will receive only RC==OK
612         This will create the state in that the XDI is waiting for the
613         additional RC and does not delivery the RC to the client. This
614         code corrects the counter of outstanding RC's in this case.
615       --------------------------------------------------------------- */
616       if ((this->More & XMOREC) > 1) {
617         this->More &= ~XMOREC;
618         this->More |= 1;
619         dtrc(dprintf("XDI: correct MORE on REMOVE A(%02x) Id:%02x",
620                      XDI_A_NR(a),Id));
621       }
622     }
623     if (Rc==OK_FC) {
624       a->FlowControlIdTable[Ch] = Id;
625       a->FlowControlSkipTable[Ch] = FALSE;
626       this->Rc = Rc;
627       this->More &= ~(XBUSY | XMOREC);
628       this->complete=0xff;
629       xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
630       CALLBACK(a, this);
631       return 0;
632     }
633     /*
634       New protocol code sends return codes that comes from release
635       of flow control condition marked with DIVA_RC_TYPE_OK_FC extended
636       information element type.
637       If like return code arrives then application is able to process
638       all return codes self and XDI should not cances return codes.
639       This return code does not decrement XMOREC partial return code
640       counter due to fact that it was no request for this return code,
641       also XMOREC was not incremented.
642       */
643     if (extended_info_type == DIVA_RC_TYPE_OK_FC) {
644       a->misc_flags_table[e_no] |= DIVA_MISC_FLAGS_NO_RC_CANCELLING;
645       this->Rc = Rc;
646       this->complete=0xff;
647       xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
648       DBG_TRC(("XDI OK_FC A(%02x) Id:%02x Ch:%02x Rc:%02x",
649       XDI_A_NR(a), Id, Ch, Rc))
650       CALLBACK(a, this);
651       return 0;
652     }
653     cancel_rc = !(a->misc_flags_table[e_no] & DIVA_MISC_FLAGS_NO_RC_CANCELLING);
654     if (cancel_rc && (a->FlowControlIdTable[Ch] == Id))
655     {
656       a->FlowControlIdTable[Ch] = 0;
657       if ((Rc != OK) || !a->FlowControlSkipTable[Ch])
658       {
659         this->Rc = Rc;
660         if (Ch == this->ReqCh)
661         {
662           this->More &=~(XBUSY | XMOREC);
663           this->complete=0xff;
664         }
665         xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
666         CALLBACK(a, this);
667       }
668       return 0;
669     }
670     if (this->More &XMOREC)
671       this->More--;
672         /* call the application callback function                   */
673     if (((!cancel_rc) || (this->More & XMOREF)) && !(this->More & XMOREC)) {
674       this->Rc = Rc;
675       this->More &=~XBUSY;
676       this->complete=0xff;
677       xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]);
678       CALLBACK(a, this);
679     }
680     return 0;
681   }
682         /* if it's an ASSIGN return code check if it's a return     */
683         /* code to an ASSIGN request from us                        */
684   if((Rc &0xf0)==ASSIGN_RC) {
685     e_no = get_assign(a, Ref);
686     if(e_no) {
687       this = entity_ptr(a,e_no);
688       this->Id = Id;
689       xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 2, a->IdTypeTable[this->No]);
690         /* call the application callback function                   */
691       this->Rc = Rc;
692       this->More &=~XBUSY;
693       this->complete=0xff;
694 #if defined(DIVA_ISTREAM) /* { */
695       if ((Rc == ASSIGN_OK) && a->ram_offset &&
696           (a->IdTypeTable[this->No] == NL_ID) &&
697           ((extended_info_type == DIVA_RC_TYPE_RX_DMA) ||
698           (extended_info_type == DIVA_RC_TYPE_CMA_PTR)) &&
699           extended_info) {
700         dword offset = (*(a->ram_offset)) (a);
701         dword tmp[2];
702         extended_info -= offset;
703 #ifdef PLATFORM_GT_32BIT
704         a->ram_in_dw(a, (void*)ULongToPtr(extended_info), (dword*)&tmp[0], 2);
705 #else
706         a->ram_in_dw(a, (void*)extended_info, (dword*)&tmp[0], 2);
707 #endif
708         a->tx_stream[Id]  = tmp[0];
709         a->rx_stream[Id]  = tmp[1];
710         if (extended_info_type == DIVA_RC_TYPE_RX_DMA) {
711           DBG_TRC(("Id=0x%x RxDMA=%08x:%08x",
712                     Id, a->tx_stream[Id], a->rx_stream[Id]))
713           a->misc_flags_table[this->No] |= DIVA_MISC_FLAGS_RX_DMA;
714         } else {
715           DBG_TRC(("Id=0x%x CMA=%08x:%08x",
716                     Id, a->tx_stream[Id], a->rx_stream[Id]))
717           a->misc_flags_table[this->No] &= ~DIVA_MISC_FLAGS_RX_DMA;
718           a->rx_pos[Id]     = 0;
719           a->rx_stream[Id] -= offset;
720         }
721         a->tx_pos[Id]     = 0;
722         a->tx_stream[Id] -= offset;
723       } else {
724         a->tx_stream[Id] = 0;
725         a->rx_stream[Id] = 0;
726         a->misc_flags_table[this->No] &= ~DIVA_MISC_FLAGS_RX_DMA;
727       }
728 #endif /* } */
729       CALLBACK(a, this);
730       if(Rc==ASSIGN_OK) {
731         a->IdTable[Id] = e_no;
732       }
733       else
734       {
735         free_entity(a, e_no);
736         for (i = 0; i < 256; i++)
737         {
738           if (a->FlowControlIdTable[i] == Id)
739             a->FlowControlIdTable[i] = 0;
740         }
741         a->IdTable[Id] = 0;
742         this->Id = 0;
743       }
744       return 1;
745     }
746   }
747   return 2;
748 }
749 /*------------------------------------------------------------------*/
750 /* indication handler                                               */
751 /*------------------------------------------------------------------*/
752 byte isdn_ind(ADAPTER * a,
753               byte Ind,
754               byte Id,
755               byte Ch,
756               PBUFFER * RBuffer,
757               byte MInd,
758               word MLength)
759 {
760   ENTITY  * this;
761   word clength;
762   word offset;
763   BUFFERS  *R;
764   byte* cma = 0;
765 #ifdef USE_EXTENDED_DEBUGS
766   {
767     DBG_TRC(("<A%d Id=0x%x Ind=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, Id, Ind))
768   }
769 #else
770   dbug(dprintf("isdn_ind(Ind=%x,Id=%x,Ch=%x)",Ind,Id,Ch));
771 #endif
772   if(a->IdTable[Id]) {
773     this = entity_ptr(a,a->IdTable[Id]);
774     this->IndCh = Ch;
775     xdi_xlog_ind (XDI_A_NR(a), Id, Ch, Ind,
776                   0/* rnr_valid */, 0 /* rnr */, a->IdTypeTable[this->No]);
777         /* if the Receive More flag is not yet set, this is the     */
778         /* first buffer of the packet                               */
779     if(this->RCurrent==0xff) {
780         /* check for receive buffer chaining                        */
781       if(Ind==this->MInd) {
782         this->complete = 0;
783         this->Ind = MInd;
784       }
785       else {
786         this->complete = 1;
787         this->Ind = Ind;
788       }
789         /* call the application callback function for the receive   */
790         /* look ahead                                               */
791       this->RLength = MLength;
792 #if defined(DIVA_ISTREAM)
793       if ((a->rx_stream[this->Id] ||
794            (a->misc_flags_table[this->No] & DIVA_MISC_FLAGS_RX_DMA)) &&
795           ((Ind == N_DATA) ||
796            (a->protocol_capabilities & PROTCAP_CMA_ALLPR))) {
797         PISDN_ADAPTER IoAdapter = (PISDN_ADAPTER)a->io ;
798         if (a->misc_flags_table[this->No] & DIVA_MISC_FLAGS_RX_DMA) {
799 #if defined(DIVA_IDI_RX_DMA)
800           dword d;
801           diva_get_dma_map_entry (\
802                    (struct _diva_dma_map_entry*)IoAdapter->dma_map,
803                    (int)a->rx_stream[this->Id], (void**)&cma, &d);
804 #else
805           cma = &a->stream_buffer[0];
806           cma[0] = cma[1] = cma[2] = cma[3] = 0;
807 #endif
808           this->RLength = MLength = (word)*(dword*)cma;
809           cma += 4;
810         } else {
811         int final = 0;
812         cma = &a->stream_buffer[0];
813         this->RLength = MLength = (word)diva_istream_read (a,
814                                                      Id,
815                                                      cma,
816                                                      sizeof(a->stream_buffer),
817                                                      &final, 0, 0);
818         }
819         IoAdapter->RBuffer.length = MIN(MLength, 270);
820         if (IoAdapter->RBuffer.length != MLength) {
821           this->complete = 0;
822         } else {
823           this->complete = 1;
824         }
825         memcpy (IoAdapter->RBuffer.P, cma, IoAdapter->RBuffer.length) ;
826         this->RBuffer = (DBUFFER *)&IoAdapter->RBuffer ;
827       }
828 #endif
829       if (!cma) {
830         a->ram_look_ahead(a, RBuffer, this);
831       }
832       this->RNum = 0;
833       CALLBACK(a, this);
834         /* map entity ptr, selector could be re-mapped by call to   */
835         /* IDI from within callback                                 */
836       this = entity_ptr(a,a->IdTable[Id]);
837       xdi_xlog_ind (XDI_A_NR(a), Id, Ch, Ind,
838           1/* rnr_valid */, this->RNR/* rnr */, a->IdTypeTable[this->No]);
839         /* check for RNR                                            */
840       if(this->RNR==1) {
841         this->RNR = 0;
842         return 1;
843       }
844         /* if no buffers are provided by the application, the       */
845         /* application want to copy the data itself including       */
846         /* N_MDATA/LL_MDATA chaining                                */
847       if(!this->RNR && !this->RNum) {
848         xdi_xlog_ind (XDI_A_NR(a), Id, Ch, Ind,
849             2/* rnr_valid */, 0/* rnr */, a->IdTypeTable[this->No]);
850         return 0;
851       }
852         /* if there is no RNR, set the More flag                    */
853       this->RCurrent = 0;
854       this->ROffset = 0;
855     }
856     if(this->RNR==2) {
857       if(Ind!=this->MInd) {
858         this->RCurrent = 0xff;
859         this->RNR = 0;
860       }
861       return 0;
862     }
863         /* if we have received buffers from the application, copy   */
864         /* the data into these buffers                              */
865     offset = 0;
866     R = PTR_R(a,this);
867     do {
868       if(this->ROffset==R[this->RCurrent].PLength) {
869         this->ROffset = 0;
870         this->RCurrent++;
871       }
872       if (cma) {
873         clength = MIN(MLength, R[this->RCurrent].PLength-this->ROffset);
874       } else {
875         clength = MIN(a->ram_inw(a, &RBuffer->length)-offset,
876                       R[this->RCurrent].PLength-this->ROffset);
877       }
878       if(R[this->RCurrent].P) {
879         if (cma) {
880           memcpy (PTR_P(a,this,&R[this->RCurrent].P[this->ROffset]),
881                   &cma[offset],
882                   clength);
883         } else {
884           a->ram_in_buffer(a,
885                            &RBuffer->P[offset],
886                            PTR_P(a,this,&R[this->RCurrent].P[this->ROffset]),
887                            clength);
888         }
889       }
890       offset +=clength;
891       this->ROffset +=clength;
892       if (cma) {
893         if (offset >= MLength) {
894           break;
895         }
896         continue;
897       }
898     } while(offset<(a->ram_inw(a, &RBuffer->length)));
899         /* if it's the last buffer of the packet, call the          */
900         /* application callback function for the receive complete   */
901         /* call                                                     */
902     if(Ind!=this->MInd) {
903       R[this->RCurrent].PLength = this->ROffset;
904       if(this->ROffset) this->RCurrent++;
905       this->RNum = this->RCurrent;
906       this->RCurrent = 0xff;
907       this->Ind = Ind;
908       this->complete = 2;
909       xdi_xlog_ind (XDI_A_NR(a), Id, Ch, Ind,
910           3/* rnr_valid */, 0/* rnr */, a->IdTypeTable[this->No]);
911       CALLBACK(a, this);
912     }
913     return 0;
914   }
915   return 2;
916 }
917 /* -----------------------------------------------------------
918    This function works in the same way as xlog on the
919    active board
920    ----------------------------------------------------------- */
921 void xdi_xlog (byte *msg, word code, int length) {
922 #if defined(XDI_USE_XLOG)
923   xdi_dbg_xlog ("\x00\x02", msg, code, length);
924 #endif
925 }
926 /* -----------------------------------------------------------
927     This function writes the information about the Return Code
928     processing in the trace buffer. Trace ID is 221.
929     INPUT:
930         Adapter - system unicue adapter number (0 ... 255)
931         Id      - Id of the entity that had sent this return code
932         Ch      - Channel of the entity that had sent this return code
933         Rc      - return code value
934         cb:       (0...2)
935                   switch (cb) {
936                    case 0: printf ("DELIVERY"); break;
937                    case 1: printf ("CALLBACK"); break;
938                    case 2: printf ("ASSIGN"); break;
939                   }
940                   DELIVERY - have entered isdn_rc with this RC
941                   CALLBACK - about to make callback to the application
942                              for this RC
943                   ASSIGN   - about to make callback for RC that is result
944                              of ASSIGN request. It is no DELIVERY message
945                              before of this message
946         type   - the Id that was sent by the ASSIGN of this entity.
947                  This should be global Id like NL_ID, DSIG_ID, MAN_ID.
948                  An unknown Id will cause "?-" in the front of the request.
949                  In this case the log.c is to be extended.
950    ----------------------------------------------------------- */
951 static void xdi_xlog_rc_event (byte Adapter,
952                                byte Id, byte Ch, byte Rc, byte cb, byte type) {
953 #if defined(XDI_USE_XLOG)
954   word LogInfo[4];
955   WRITE_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8)));
956   WRITE_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8)));
957   WRITE_WORD(&LogInfo[2], ((word)Rc | (word)(type << 8)));
958   WRITE_WORD(&LogInfo[3], cb);
959   xdi_xlog ((byte*)&LogInfo[0], 221, sizeof(LogInfo));
960 #endif
961 }
962 /* ------------------------------------------------------------------------
963     This function writes the information about the request processing
964     in the trace buffer. Trace ID is 220.
965     INPUT:
966         Adapter - system unicue adapter number (0 ... 255)
967         Id      - Id of the entity that had sent this request
968         Ch      - Channel of the entity that had sent this request
969         Req     - Code of the request
970         type    - the Id that was sent by the ASSIGN of this entity.
971                   This should be global Id like NL_ID, DSIG_ID, MAN_ID.
972                   An unknown Id will cause "?-" in the front of the request.
973                   In this case the log.c is to be extended.
974    ------------------------------------------------------------------------ */
975 static void xdi_xlog_request (byte Adapter, byte Id,
976                               byte Ch, byte Req, byte type) {
977 #if defined(XDI_USE_XLOG)
978   word LogInfo[3];
979   WRITE_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8)));
980   WRITE_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8)));
981   WRITE_WORD(&LogInfo[2], ((word)Req | (word)(type << 8)));
982   xdi_xlog ((byte*)&LogInfo[0], 220, sizeof(LogInfo));
983 #endif
984 }
985 /* ------------------------------------------------------------------------
986     This function writes the information about the indication processing
987     in the trace buffer. Trace ID is 222.
988     INPUT:
989         Adapter - system unicue adapter number (0 ... 255)
990         Id      - Id of the entity that had sent this indication
991         Ch      - Channel of the entity that had sent this indication
992         Ind     - Code of the indication
993         rnr_valid: (0 .. 3) supported
994           switch (rnr_valid) {
995             case 0: printf ("DELIVERY"); break;
996             case 1: printf ("RNR=%d", rnr);
997             case 2: printf ("RNum=0");
998             case 3: printf ("COMPLETE");
999           }
1000           DELIVERY - indication entered isdn_rc function
1001           RNR=...  - application had returned RNR=... after the
1002                      look ahead callback
1003           RNum=0   - aplication had not returned any buffer to copy
1004                      this indication and will copy it self
1005           COMPLETE - XDI had copied the data to the buffers provided
1006                      bu the application and is about to issue the
1007                      final callback
1008         rnr:  Look case 1 of the rnr_valid
1009         type: the Id that was sent by the ASSIGN of this entity. This should
1010               be global Id like NL_ID, DSIG_ID, MAN_ID. An unknown Id will
1011               cause "?-" in the front of the request. In this case the
1012               log.c is to be extended.
1013    ------------------------------------------------------------------------ */
1014 static void xdi_xlog_ind (byte Adapter,
1015                           byte Id,
1016                           byte Ch,
1017                           byte Ind,
1018                           byte rnr_valid,
1019                           byte rnr,
1020                           byte type) {
1021 #if defined(XDI_USE_XLOG)
1022   word LogInfo[4];
1023   WRITE_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8)));
1024   WRITE_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8)));
1025   WRITE_WORD(&LogInfo[2], ((word)Ind | (word)(type << 8)));
1026   WRITE_WORD(&LogInfo[3], ((word)rnr | (word)(rnr_valid << 8)));
1027   xdi_xlog ((byte*)&LogInfo[0], 222, sizeof(LogInfo));
1028 #endif
1029 }