Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
di.c
Go to the documentation of this file.
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);
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 /*------------------------------------------------------------------*/
79 {
80  byte e_no;
81  ENTITY *this = NULL;
82  BUFFERS *X;
83  word length;
84  word i;
85  word clength;
86  REQ *ReqOut;
87  byte more;
88  byte ReadyCount;
89  byte ReqCount;
90  byte Id;
91  dtrc(dprintf("pr_out"));
92  /* while a request is pending ... */
93  e_no = look_req(a);
94  if (!e_no)
95  {
96  dtrc(dprintf("no_req"));
97  return;
98  }
99  ReadyCount = pr_ready(a);
100  if (!ReadyCount)
101  {
102  dtrc(dprintf("not_ready"));
103  return;
104  }
105  ReqCount = 0;
106  while (e_no && ReadyCount) {
107  next_req(a);
108  this = entity_ptr(a, e_no);
109 #ifdef USE_EXTENDED_DEBUGS
110  if (!this)
111  {
112  DBG_FTL(("XDI: [%02x] !A%d ==> NULL entity ptr - try to ignore",
113  xdi_xlog_sec++, (int)((ISDN_ADAPTER *)a->io)->ANum))
114  e_no = look_req(a);
115  ReadyCount--;
116  continue;
117  }
118  {
119  DBG_TRC((">A%d Id=0x%x Req=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, this->Id, this->Req))
120  }
121 #else
122  dbug(dprintf("out:Req=%x,Id=%x,Ch=%x", this->Req, this->Id, this->ReqCh));
123 #endif
124  /* get address of next available request buffer */
125  ReqOut = (REQ *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextReq)];
126 #if defined(DIVA_ISTREAM)
127  if (!(a->tx_stream[this->Id] &&
128  this->Req == N_DATA)) {
129 #endif
130  /* now copy the data from the current data buffer into the */
131  /* adapters request buffer */
132  length = 0;
133  i = this->XCurrent;
134  X = PTR_X(a, this);
135  while (i < this->XNum && length < 270) {
136  clength = min((word)(270 - length), (word)(X[i].PLength-this->XOffset));
137  a->ram_out_buffer(a,
138  &ReqOut->XBuffer.P[length],
139  PTR_P(a, this, &X[i].P[this->XOffset]),
140  clength);
141  length += clength;
142  this->XOffset += clength;
143  if (this->XOffset == X[i].PLength) {
144  this->XCurrent = (byte)++i;
145  this->XOffset = 0;
146  }
147  }
148 #if defined(DIVA_ISTREAM)
149  } else { /* Use CMA extension in order to transfer data to the card */
150  i = this->XCurrent;
151  X = PTR_X(a, this);
152  while (i < this->XNum) {
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) {
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 /*------------------------------------------------------------------*/
256 {
257  byte Count;
258  RC *RcIn;
259  IND *IndIn;
260  byte c;
261  byte RNRId;
262  byte Rc;
263  byte Ind;
264  /* if return codes are available ... */
265  if ((Count = a->ram_in(a, &PR_RAM->RcOutput)) != 0) {
266  dtrc(dprintf("#Rc=%x", Count));
267  /* get the buffer address of the first return code */
268  RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextRc)];
269  /* for all return codes do ... */
270  while (Count--) {
271  if ((Rc = a->ram_in(a, &RcIn->Rc)) != 0) {
272  dword tmp[2];
273  /*
274  Get extended information, associated with return code
275  */
276  a->ram_in_buffer(a,
277  &RcIn->Reserved2[0],
278  (byte *)&tmp[0],
279  8);
280  /* call return code handler, if it is not our return code */
281  /* the handler returns 2 */
282  /* for all return codes we process, we clear the Rc field */
283  isdn_rc(a,
284  Rc,
285  a->ram_in(a, &RcIn->RcId),
286  a->ram_in(a, &RcIn->RcCh),
287  a->ram_inw(a, &RcIn->Reference),
288  tmp[0], /* type of extended information */
289  tmp[1]); /* extended information */
290  a->ram_out(a, &RcIn->Rc, 0);
291  }
292  /* get buffer address of next return code */
293  RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &RcIn->next)];
294  }
295  /* clear all return codes (no chaining!) */
296  a->ram_out(a, &PR_RAM->RcOutput, 0);
297  /* call output function */
298  pr_out(a);
299  }
300  /* clear RNR flag */
301  RNRId = 0;
302  /* if indications are available ... */
303  if ((Count = a->ram_in(a, &PR_RAM->IndOutput)) != 0) {
304  dtrc(dprintf("#Ind=%x", Count));
305  /* get the buffer address of the first indication */
306  IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextInd)];
307  /* for all indications do ... */
308  while (Count--) {
309  /* if the application marks an indication as RNR, all */
310  /* indications from the same Id delivered in this interrupt */
311  /* are marked RNR */
312  if (RNRId && RNRId == a->ram_in(a, &IndIn->IndId)) {
313  a->ram_out(a, &IndIn->Ind, 0);
314  a->ram_out(a, &IndIn->RNR, true);
315  }
316  else {
317  Ind = a->ram_in(a, &IndIn->Ind);
318  if (Ind) {
319  RNRId = 0;
320  /* call indication handler, a return value of 2 means chain */
321  /* a return value of 1 means RNR */
322  /* for all indications we process, we clear the Ind field */
323  c = isdn_ind(a,
324  Ind,
325  a->ram_in(a, &IndIn->IndId),
326  a->ram_in(a, &IndIn->IndCh),
327  &IndIn->RBuffer,
328  a->ram_in(a, &IndIn->MInd),
329  a->ram_inw(a, &IndIn->MLength));
330  if (c == 1) {
331  dtrc(dprintf("RNR"));
332  a->ram_out(a, &IndIn->Ind, 0);
333  RNRId = a->ram_in(a, &IndIn->IndId);
334  a->ram_out(a, &IndIn->RNR, true);
335  }
336  }
337  }
338  /* get buffer address of next indication */
339  IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &IndIn->next)];
340  }
341  a->ram_out(a, &PR_RAM->IndOutput, 0);
342  }
343  return false;
344 }
346 {
347  return a->ram_in(a, (void *)0x3fe);
348 }
350 {
351  a->ram_out(a, (void *)0x3fe, 0);
352 }
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,
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 */
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;
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) {
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 static 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) ||
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;
608  (struct _diva_dma_map_entry *)IoAdapter->dma_map,
609  (int)a->rx_stream[this->Id], (void **)&cma, &d);
610 #else
611  cma = &a->stream_buffer[0];
612  cma[0] = cma[1] = cma[2] = cma[3] = 0;
613 #endif
614  this->RLength = MLength = (word)*(dword *)cma;
615  cma += 4;
616  } else {
617  int final = 0;
618  cma = &a->stream_buffer[0];
619  this->RLength = MLength = (word)diva_istream_read(a,
620  Id,
621  cma,
622  sizeof(a->stream_buffer),
623  &final, NULL, NULL);
624  }
625  IoAdapter->RBuffer.length = min(MLength, (word)270);
626  if (IoAdapter->RBuffer.length != MLength) {
627  this->complete = 0;
628  } else {
629  this->complete = 1;
630  }
631  memcpy(IoAdapter->RBuffer.P, cma, IoAdapter->RBuffer.length);
632  this->RBuffer = (DBUFFER *)&IoAdapter->RBuffer;
633  }
634 #endif
635  if (!cma) {
636  a->ram_look_ahead(a, RBuffer, this);
637  }
638  this->RNum = 0;
639  CALLBACK(a, this);
640  /* map entity ptr, selector could be re-mapped by call to */
641  /* IDI from within callback */
642  this = entity_ptr(a, a->IdTable[Id]);
643  xdi_xlog_ind(XDI_A_NR(a), Id, Ch, Ind,
644  1/* rnr_valid */, this->RNR/* rnr */, a->IdTypeTable[this->No]);
645  /* check for RNR */
646  if (this->RNR == 1) {
647  this->RNR = 0;
648  return 1;
649  }
650  /* if no buffers are provided by the application, the */
651  /* application want to copy the data itself including */
652  /* N_MDATA/LL_MDATA chaining */
653  if (!this->RNR && !this->RNum) {
654  xdi_xlog_ind(XDI_A_NR(a), Id, Ch, Ind,
655  2/* rnr_valid */, 0/* rnr */, a->IdTypeTable[this->No]);
656  return 0;
657  }
658  /* if there is no RNR, set the More flag */
659  this->RCurrent = 0;
660  this->ROffset = 0;
661  }
662  if (this->RNR == 2) {
663  if (Ind != this->MInd) {
664  this->RCurrent = 0xff;
665  this->RNR = 0;
666  }
667  return 0;
668  }
669  /* if we have received buffers from the application, copy */
670  /* the data into these buffers */
671  offset = 0;
672  R = PTR_R(a, this);
673  do {
674  if (this->ROffset == R[this->RCurrent].PLength) {
675  this->ROffset = 0;
676  this->RCurrent++;
677  }
678  if (cma) {
679  clength = min(MLength, (word)(R[this->RCurrent].PLength-this->ROffset));
680  } else {
681  clength = min(a->ram_inw(a, &RBuffer->length)-offset,
682  R[this->RCurrent].PLength-this->ROffset);
683  }
684  if (R[this->RCurrent].P) {
685  if (cma) {
686  memcpy(PTR_P(a, this, &R[this->RCurrent].P[this->ROffset]),
687  &cma[offset],
688  clength);
689  } else {
690  a->ram_in_buffer(a,
691  &RBuffer->P[offset],
692  PTR_P(a, this, &R[this->RCurrent].P[this->ROffset]),
693  clength);
694  }
695  }
696  offset += clength;
697  this->ROffset += clength;
698  if (cma) {
699  if (offset >= MLength) {
700  break;
701  }
702  continue;
703  }
704  } while (offset < (a->ram_inw(a, &RBuffer->length)));
705  /* if it's the last buffer of the packet, call the */
706  /* application callback function for the receive complete */
707  /* call */
708  if (Ind != this->MInd) {
709  R[this->RCurrent].PLength = this->ROffset;
710  if (this->ROffset) this->RCurrent++;
711  this->RNum = this->RCurrent;
712  this->RCurrent = 0xff;
713  this->Ind = Ind;
714  this->complete = 2;
715  xdi_xlog_ind(XDI_A_NR(a), Id, Ch, Ind,
716  3/* rnr_valid */, 0/* rnr */, a->IdTypeTable[this->No]);
717  CALLBACK(a, this);
718  }
719  return 0;
720  }
721  return 2;
722 }
723 #if defined(XDI_USE_XLOG)
724 /* -----------------------------------------------------------
725  This function works in the same way as xlog on the
726  active board
727  ----------------------------------------------------------- */
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 - 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
835 }