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 /*------------------------------------------------------------------*/
pr_out(ADAPTER * a)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), (word)(X[i].PLength-this->XOffset));
137 				a->ram_out_buffer(a,
138 						  &ReqOut->XBuffer.P[length],
139 						  PTR_P(a, this, &X[i].P[this->XOffset]),
140 						  clength);
141 				length += clength;
142 				this->XOffset += clength;
143 				if (this->XOffset == X[i].PLength) {
144 					this->XCurrent = (byte)++i;
145 					this->XOffset = 0;
146 				}
147 			}
148 #if defined(DIVA_ISTREAM)
149 		} else { /* Use CMA extension in order to transfer data to the card */
150 			i = this->XCurrent;
151 			X = PTR_X(a, this);
152 			while (i < this->XNum) {
153 				diva_istream_write(a,
154 						   this->Id,
155 						   PTR_P(a, this, &X[i].P[0]),
156 						   X[i].PLength,
157 						   ((i + 1) == this->XNum),
158 						   0, 0);
159 				this->XCurrent = (byte)++i;
160 			}
161 			length = 0;
162 		}
163 #endif
164 		a->ram_outw(a, &ReqOut->XBuffer.length, length);
165 		a->ram_out(a, &ReqOut->ReqId, this->Id);
166 		a->ram_out(a, &ReqOut->ReqCh, this->ReqCh);
167 		/* if it's a specific request (no ASSIGN) ...                */
168 		if (this->Id & 0x1f) {
169 			/* if buffers are left in the list of data buffers do       */
170 			/* do chaining (LL_MDATA, N_MDATA)                          */
171 			this->More++;
172 			if (i < this->XNum && this->MInd) {
173 				xdi_xlog_request(XDI_A_NR(a), this->Id, this->ReqCh, this->MInd,
174 						 a->IdTypeTable[this->No]);
175 				a->ram_out(a, &ReqOut->Req, this->MInd);
176 				more = true;
177 			}
178 			else {
179 				xdi_xlog_request(XDI_A_NR(a), this->Id, this->ReqCh, this->Req,
180 						 a->IdTypeTable[this->No]);
181 				this->More |= XMOREF;
182 				a->ram_out(a, &ReqOut->Req, this->Req);
183 				more = false;
184 				if (a->FlowControlIdTable[this->ReqCh] == this->Id)
185 					a->FlowControlSkipTable[this->ReqCh] = true;
186 				/*
187 				  Note that remove request was sent to the card
188 				*/
189 				if (this->Req == REMOVE) {
190 					a->misc_flags_table[e_no] |= DIVA_MISC_FLAGS_REMOVE_PENDING;
191 				}
192 			}
193 			/* if we did chaining, this entity is put back into the     */
194 			/* request queue                                            */
195 			if (more) {
196 				req_queue(a, this->No);
197 			}
198 		}
199 		/* else it's a ASSIGN                                       */
200 		else {
201 			/* save the request code used for buffer chaining           */
202 			this->MInd = 0;
203 			if (this->Id == BLLC_ID) this->MInd = LL_MDATA;
204 			if (this->Id == NL_ID ||
205 			    this->Id == TASK_ID ||
206 			    this->Id == MAN_ID
207 				) this->MInd = N_MDATA;
208 			/* send the ASSIGN                                          */
209 			a->IdTypeTable[this->No] = this->Id;
210 			xdi_xlog_request(XDI_A_NR(a), this->Id, this->ReqCh, this->Req, this->Id);
211 			this->More |= XMOREF;
212 			a->ram_out(a, &ReqOut->Req, this->Req);
213 			/* save the reference of the ASSIGN                         */
214 			assign_queue(a, this->No, a->ram_inw(a, &ReqOut->Reference));
215 		}
216 		a->ram_outw(a, &PR_RAM->NextReq, a->ram_inw(a, &ReqOut->next));
217 		ReadyCount--;
218 		ReqCount++;
219 		e_no = look_req(a);
220 	}
221 	/* send the filled request buffers to the ISDN adapter      */
222 	a->ram_out(a, &PR_RAM->ReqInput,
223 		   (byte)(a->ram_in(a, &PR_RAM->ReqInput) + ReqCount));
224 	/* if it is a 'unreturncoded' UREMOVE request, remove the  */
225 	/* Id from our table after sending the request             */
226 	if (this && (this->Req == UREMOVE) && this->Id) {
227 		Id = this->Id;
228 		e_no = a->IdTable[Id];
229 		free_entity(a, e_no);
230 		for (i = 0; i < 256; i++)
231 		{
232 			if (a->FlowControlIdTable[i] == Id)
233 				a->FlowControlIdTable[i] = 0;
234 		}
235 		a->IdTable[Id] = 0;
236 		this->Id = 0;
237 	}
238 }
pr_ready(ADAPTER * a)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 /*------------------------------------------------------------------*/
pr_dpc(ADAPTER * a)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 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 }
scom_test_int(ADAPTER * a)345 byte scom_test_int(ADAPTER *a)
346 {
347 	return a->ram_in(a, (void *)0x3fe);
348 }
scom_clear_int(ADAPTER * a)349 void scom_clear_int(ADAPTER *a)
350 {
351 	a->ram_out(a, (void *)0x3fe, 0);
352 }
353 /*------------------------------------------------------------------*/
354 /* return code handler                                              */
355 /*------------------------------------------------------------------*/
isdn_rc(ADAPTER * a,byte Rc,byte Id,byte Ch,word Ref,dword extended_info_type,dword extended_info)356 static byte isdn_rc(ADAPTER *a,
357 		    byte Rc,
358 		    byte Id,
359 		    byte Ch,
360 		    word Ref,
361 		    dword extended_info_type,
362 		    dword extended_info)
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 /*------------------------------------------------------------------*/
isdn_ind(ADAPTER * a,byte Ind,byte Id,byte Ch,PBUFFER * RBuffer,byte MInd,word MLength)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) ||
602 			     (a->protocol_capabilities & PROTCAP_CMA_ALLPR))) {
603 				PISDN_ADAPTER IoAdapter = (PISDN_ADAPTER)a->io;
604 				if (a->misc_flags_table[this->No] & DIVA_MISC_FLAGS_RX_DMA) {
605 #if defined(DIVA_IDI_RX_DMA)
606 					dword d;
607 					diva_get_dma_map_entry(\
608 						(struct _diva_dma_map_entry *)IoAdapter->dma_map,
609 						(int)a->rx_stream[this->Id], (void **)&cma, &d);
610 #else
611 					cma = &a->stream_buffer[0];
612 					cma[0] = cma[1] = cma[2] = cma[3] = 0;
613 #endif
614 					this->RLength = MLength = (word)*(dword *)cma;
615 					cma += 4;
616 				} else {
617 					int final = 0;
618 					cma = &a->stream_buffer[0];
619 					this->RLength = MLength = (word)diva_istream_read(a,
620 											  Id,
621 											  cma,
622 											  sizeof(a->stream_buffer),
623 											  &final, NULL, NULL);
624 				}
625 				IoAdapter->RBuffer.length = min(MLength, (word)270);
626 				if (IoAdapter->RBuffer.length != MLength) {
627 					this->complete = 0;
628 				} else {
629 					this->complete = 1;
630 				}
631 				memcpy(IoAdapter->RBuffer.P, cma, IoAdapter->RBuffer.length);
632 				this->RBuffer = (DBUFFER *)&IoAdapter->RBuffer;
633 			}
634 #endif
635 			if (!cma) {
636 				a->ram_look_ahead(a, RBuffer, this);
637 			}
638 			this->RNum = 0;
639 			CALLBACK(a, this);
640 			/* map entity ptr, selector could be re-mapped by call to   */
641 			/* IDI from within callback                                 */
642 			this = entity_ptr(a, a->IdTable[Id]);
643 			xdi_xlog_ind(XDI_A_NR(a), Id, Ch, Ind,
644 				     1/* rnr_valid */, this->RNR/* rnr */, a->IdTypeTable[this->No]);
645 			/* check for RNR                                            */
646 			if (this->RNR == 1) {
647 				this->RNR = 0;
648 				return 1;
649 			}
650 			/* if no buffers are provided by the application, the       */
651 			/* application want to copy the data itself including       */
652 			/* N_MDATA/LL_MDATA chaining                                */
653 			if (!this->RNR && !this->RNum) {
654 				xdi_xlog_ind(XDI_A_NR(a), Id, Ch, Ind,
655 					     2/* rnr_valid */, 0/* rnr */, a->IdTypeTable[this->No]);
656 				return 0;
657 			}
658 			/* if there is no RNR, set the More flag                    */
659 			this->RCurrent = 0;
660 			this->ROffset = 0;
661 		}
662 		if (this->RNR == 2) {
663 			if (Ind != this->MInd) {
664 				this->RCurrent = 0xff;
665 				this->RNR = 0;
666 			}
667 			return 0;
668 		}
669 		/* if we have received buffers from the application, copy   */
670 		/* the data into these buffers                              */
671 		offset = 0;
672 		R = PTR_R(a, this);
673 		do {
674 			if (this->ROffset == R[this->RCurrent].PLength) {
675 				this->ROffset = 0;
676 				this->RCurrent++;
677 			}
678 			if (cma) {
679 				clength = min(MLength, (word)(R[this->RCurrent].PLength-this->ROffset));
680 			} else {
681 				clength = min(a->ram_inw(a, &RBuffer->length)-offset,
682 					      R[this->RCurrent].PLength-this->ROffset);
683 			}
684 			if (R[this->RCurrent].P) {
685 				if (cma) {
686 					memcpy(PTR_P(a, this, &R[this->RCurrent].P[this->ROffset]),
687 					       &cma[offset],
688 					       clength);
689 				} else {
690 					a->ram_in_buffer(a,
691 							 &RBuffer->P[offset],
692 							 PTR_P(a, this, &R[this->RCurrent].P[this->ROffset]),
693 							 clength);
694 				}
695 			}
696 			offset += clength;
697 			this->ROffset += clength;
698 			if (cma) {
699 				if (offset >= MLength) {
700 					break;
701 				}
702 				continue;
703 			}
704 		} while (offset < (a->ram_inw(a, &RBuffer->length)));
705 		/* if it's the last buffer of the packet, call the          */
706 		/* application callback function for the receive complete   */
707 		/* call                                                     */
708 		if (Ind != this->MInd) {
709 			R[this->RCurrent].PLength = this->ROffset;
710 			if (this->ROffset) this->RCurrent++;
711 			this->RNum = this->RCurrent;
712 			this->RCurrent = 0xff;
713 			this->Ind = Ind;
714 			this->complete = 2;
715 			xdi_xlog_ind(XDI_A_NR(a), Id, Ch, Ind,
716 				     3/* rnr_valid */, 0/* rnr */, a->IdTypeTable[this->No]);
717 			CALLBACK(a, this);
718 		}
719 		return 0;
720 	}
721 	return 2;
722 }
723 #if defined(XDI_USE_XLOG)
724 /* -----------------------------------------------------------
725    This function works in the same way as xlog on the
726    active board
727    ----------------------------------------------------------- */
xdi_xlog(byte * msg,word code,int length)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    ----------------------------------------------------------- */
xdi_xlog_rc_event(byte Adapter,byte Id,byte Ch,byte Rc,byte cb,byte type)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    ------------------------------------------------------------------------ */
xdi_xlog_request(byte Adapter,byte Id,byte Ch,byte Req,byte type)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    ------------------------------------------------------------------------ */
xdi_xlog_ind(byte Adapter,byte Id,byte Ch,byte Ind,byte rnr_valid,byte rnr,byte type)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 }
836