Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | |
2 | /* | |
3 | * | |
4 | Copyright (c) Eicon Networks, 2002. | |
5 | * | |
6 | This source file is supplied for the use with | |
7 | Eicon Networks range of DIVA Server Adapters. | |
8 | * | |
9 | Eicon File Revision : 2.1 | |
10 | * | |
11 | This program is free software; you can redistribute it and/or modify | |
12 | it under the terms of the GNU General Public License as published by | |
13 | the Free Software Foundation; either version 2, or (at your option) | |
14 | any later version. | |
15 | * | |
16 | This program is distributed in the hope that it will be useful, | |
17 | but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY | |
18 | implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
19 | See the GNU General Public License for more details. | |
20 | * | |
21 | You should have received a copy of the GNU General Public License | |
22 | along with this program; if not, write to the Free Software | |
23 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
24 | * | |
25 | */ | |
26 | #include "platform.h" | |
27 | #include "pc.h" | |
28 | #include "pr_pc.h" | |
29 | #include "di_defs.h" | |
30 | #include "di.h" | |
31 | #if !defined USE_EXTENDED_DEBUGS | |
32 | #include "dimaint.h" | |
33 | #else | |
34 | #define dprintf | |
35 | #endif | |
36 | #include "io.h" | |
37 | #include "dfifo.h" | |
38 | #define PR_RAM ((struct pr_ram *)0) | |
39 | #define RAM ((struct dual *)0) | |
40 | /*------------------------------------------------------------------*/ | |
41 | /* local function prototypes */ | |
42 | /*------------------------------------------------------------------*/ | |
43 | void pr_out(ADAPTER * a); | |
44 | byte pr_dpc(ADAPTER * a); | |
45 | static byte pr_ready(ADAPTER * a); | |
46 | static byte isdn_rc(ADAPTER *, byte, byte, byte, word, dword, dword); | |
47 | static byte isdn_ind(ADAPTER *, byte, byte, byte, PBUFFER *, byte, word); | |
48 | /* ----------------------------------------------------------------- | |
49 | Functions used for the extended XDI Debug | |
50 | macros | |
51 | global convergence counter (used by all adapters) | |
52 | Look by the implementation part of the functions | |
53 | about the parameters. | |
54 | If you change the dubugging parameters, then you should update | |
55 | the aididbg.doc in the IDI doc's. | |
56 | ----------------------------------------------------------------- */ | |
57 | #if defined(XDI_USE_XLOG) | |
58 | #define XDI_A_NR(_x_) ((byte)(((ISDN_ADAPTER *)(_x_->io))->ANum)) | |
59 | static void xdi_xlog (byte *msg, word code, int length); | |
60 | static byte xdi_xlog_sec = 0; | |
61 | #else | |
62 | #define XDI_A_NR(_x_) ((byte)0) | |
63 | #endif | |
64 | static void xdi_xlog_rc_event (byte Adapter, | |
65 | byte Id, byte Ch, byte Rc, byte cb, byte type); | |
66 | static void xdi_xlog_request (byte Adapter, byte Id, | |
67 | byte Ch, byte Req, byte type); | |
68 | static void xdi_xlog_ind (byte Adapter, | |
69 | byte Id, | |
70 | byte Ch, | |
71 | byte Ind, | |
72 | byte rnr_valid, | |
73 | byte rnr, | |
74 | byte type); | |
75 | /*------------------------------------------------------------------*/ | |
76 | /* output function */ | |
77 | /*------------------------------------------------------------------*/ | |
78 | void pr_out(ADAPTER * a) | |
79 | { | |
80 | byte e_no; | |
81 | ENTITY * this = NULL; | |
82 | BUFFERS *X; | |
83 | word length; | |
84 | word i; | |
85 | word clength; | |
86 | REQ * ReqOut; | |
87 | byte more; | |
88 | byte ReadyCount; | |
89 | byte ReqCount; | |
90 | byte Id; | |
91 | dtrc(dprintf("pr_out")); | |
92 | /* while a request is pending ... */ | |
93 | e_no = look_req(a); | |
94 | if(!e_no) | |
95 | { | |
96 | dtrc(dprintf("no_req")); | |
97 | return; | |
98 | } | |
99 | ReadyCount = pr_ready(a); | |
100 | if(!ReadyCount) | |
101 | { | |
102 | dtrc(dprintf("not_ready")); | |
103 | return; | |
104 | } | |
105 | ReqCount = 0; | |
106 | while(e_no && ReadyCount) { | |
107 | next_req(a); | |
108 | this = entity_ptr(a, e_no); | |
109 | #ifdef USE_EXTENDED_DEBUGS | |
110 | if ( !this ) | |
111 | { | |
112 | DBG_FTL(("XDI: [%02x] !A%d ==> NULL entity ptr - try to ignore", | |
113 | xdi_xlog_sec++, (int)((ISDN_ADAPTER *)a->io)->ANum)) | |
114 | e_no = look_req(a) ; | |
115 | ReadyCount-- ; | |
116 | continue ; | |
117 | } | |
118 | { | |
119 | DBG_TRC((">A%d Id=0x%x Req=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, this->Id, this->Req)) | |
120 | } | |
121 | #else | |
122 | dbug(dprintf("out:Req=%x,Id=%x,Ch=%x",this->Req,this->Id,this->ReqCh)); | |
123 | #endif | |
124 | /* get address of next available request buffer */ | |
125 | ReqOut = (REQ *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextReq)]; | |
126 | #if defined(DIVA_ISTREAM) | |
127 | if (!(a->tx_stream[this->Id] && | |
128 | this->Req == N_DATA)) { | |
129 | #endif | |
130 | /* now copy the data from the current data buffer into the */ | |
131 | /* adapters request buffer */ | |
132 | length = 0; | |
133 | i = this->XCurrent; | |
134 | X = PTR_X(a,this); | |
135 | while(i<this->XNum && length<270) { | |
e2de257c | 136 | clength = min((word)(270-length),(word)(X[i].PLength-this->XOffset)); |
1da177e4 LT |
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); | |
986c4bb8 | 176 | more = true; |
1da177e4 LT |
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); | |
986c4bb8 | 183 | more = false; |
1da177e4 | 184 | if (a->FlowControlIdTable[this->ReqCh] == this->Id) |
986c4bb8 | 185 | a->FlowControlSkipTable[this->ReqCh] = true; |
1da177e4 LT |
186 | /* |
187 | Note that remove request was sent to the card | |
188 | */ | |
189 | if (this->Req == REMOVE) { | |
190 | a->misc_flags_table[e_no] |= DIVA_MISC_FLAGS_REMOVE_PENDING; | |
191 | } | |
192 | } | |
193 | /* if we did chaining, this entity is put back into the */ | |
194 | /* request queue */ | |
195 | if(more) { | |
196 | req_queue(a,this->No); | |
197 | } | |
198 | } | |
199 | /* else it's a ASSIGN */ | |
200 | else { | |
201 | /* save the request code used for buffer chaining */ | |
202 | this->MInd = 0; | |
203 | if (this->Id==BLLC_ID) this->MInd = LL_MDATA; | |
204 | if (this->Id==NL_ID || | |
205 | this->Id==TASK_ID || | |
206 | this->Id==MAN_ID | |
207 | ) this->MInd = N_MDATA; | |
208 | /* send the ASSIGN */ | |
209 | a->IdTypeTable[this->No] = this->Id; | |
210 | xdi_xlog_request (XDI_A_NR(a),this->Id,this->ReqCh,this->Req, this->Id); | |
211 | this->More |=XMOREF; | |
212 | a->ram_out(a, &ReqOut->Req, this->Req); | |
213 | /* save the reference of the ASSIGN */ | |
214 | assign_queue(a, this->No, a->ram_inw(a, &ReqOut->Reference)); | |
215 | } | |
216 | a->ram_outw(a, &PR_RAM->NextReq, a->ram_inw(a, &ReqOut->next)); | |
217 | ReadyCount--; | |
218 | ReqCount++; | |
219 | e_no = look_req(a); | |
220 | } | |
221 | /* send the filled request buffers to the ISDN adapter */ | |
222 | a->ram_out(a, &PR_RAM->ReqInput, | |
223 | (byte)(a->ram_in(a, &PR_RAM->ReqInput) + ReqCount)); | |
224 | /* if it is a 'unreturncoded' UREMOVE request, remove the */ | |
225 | /* Id from our table after sending the request */ | |
226 | if(this && (this->Req==UREMOVE) && this->Id) { | |
227 | Id = this->Id; | |
228 | e_no = a->IdTable[Id]; | |
229 | free_entity(a, e_no); | |
230 | for (i = 0; i < 256; i++) | |
231 | { | |
232 | if (a->FlowControlIdTable[i] == Id) | |
233 | a->FlowControlIdTable[i] = 0; | |
234 | } | |
235 | a->IdTable[Id] = 0; | |
236 | this->Id = 0; | |
237 | } | |
238 | } | |
239 | static byte pr_ready(ADAPTER * a) | |
240 | { | |
241 | byte ReadyCount; | |
242 | ReadyCount = (byte)(a->ram_in(a, &PR_RAM->ReqOutput) - | |
243 | a->ram_in(a, &PR_RAM->ReqInput)); | |
244 | if(!ReadyCount) { | |
245 | if(!a->ReadyInt) { | |
246 | a->ram_inc(a, &PR_RAM->ReadyInt); | |
247 | a->ReadyInt++; | |
248 | } | |
249 | } | |
250 | return ReadyCount; | |
251 | } | |
252 | /*------------------------------------------------------------------*/ | |
253 | /* isdn interrupt handler */ | |
254 | /*------------------------------------------------------------------*/ | |
255 | byte pr_dpc(ADAPTER * a) | |
256 | { | |
257 | byte Count; | |
258 | RC * RcIn; | |
259 | IND * IndIn; | |
260 | byte c; | |
261 | byte RNRId; | |
262 | byte Rc; | |
263 | byte Ind; | |
264 | /* if return codes are available ... */ | |
265 | if((Count = a->ram_in(a, &PR_RAM->RcOutput)) != 0) { | |
266 | dtrc(dprintf("#Rc=%x",Count)); | |
267 | /* get the buffer address of the first return code */ | |
268 | RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextRc)]; | |
269 | /* for all return codes do ... */ | |
270 | while(Count--) { | |
271 | if((Rc=a->ram_in(a, &RcIn->Rc)) != 0) { | |
272 | dword tmp[2]; | |
273 | /* | |
274 | Get extended information, associated with return code | |
275 | */ | |
276 | a->ram_in_buffer(a, | |
277 | &RcIn->Reserved2[0], | |
278 | (byte*)&tmp[0], | |
279 | 8); | |
280 | /* call return code handler, if it is not our return code */ | |
281 | /* the handler returns 2 */ | |
282 | /* for all return codes we process, we clear the Rc field */ | |
283 | isdn_rc(a, | |
284 | Rc, | |
285 | a->ram_in(a, &RcIn->RcId), | |
286 | a->ram_in(a, &RcIn->RcCh), | |
287 | a->ram_inw(a, &RcIn->Reference), | |
c66ed655 | 288 | tmp[0], /* type of extended information */ |
1da177e4 LT |
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); | |
986c4bb8 | 314 | a->ram_out(a, &IndIn->RNR, true); |
1da177e4 LT |
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); | |
986c4bb8 | 334 | a->ram_out(a, &IndIn->RNR, true); |
1da177e4 LT |
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 | } | |
986c4bb8 | 343 | return false; |
1da177e4 LT |
344 | } |
345 | byte scom_test_int(ADAPTER * a) | |
346 | { | |
347 | return a->ram_in(a,(void *)0x3fe); | |
348 | } | |
349 | void scom_clear_int(ADAPTER * a) | |
350 | { | |
351 | a->ram_out(a,(void *)0x3fe,0); | |
352 | } | |
353 | /*------------------------------------------------------------------*/ | |
354 | /* return code handler */ | |
355 | /*------------------------------------------------------------------*/ | |
4ee59d54 HE |
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) | |
1da177e4 LT |
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) | |
986c4bb8 | 402 | a->RcExtensionSupported = true; |
1da177e4 LT |
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; | |
986c4bb8 | 431 | a->FlowControlSkipTable[Ch] = false; |
1da177e4 LT |
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 | /*------------------------------------------------------------------*/ | |
4ee59d54 HE |
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) | |
1da177e4 LT |
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 | } | |
e2de257c | 625 | IoAdapter->RBuffer.length = min(MLength, (word)270); |
1da177e4 LT |
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) { | |
e2de257c | 679 | clength = min(MLength, (word)(R[this->RCurrent].PLength-this->ROffset)); |
1da177e4 | 680 | } else { |
e2de257c | 681 | clength = min(a->ram_inw(a, &RBuffer->length)-offset, |
1da177e4 LT |
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 | |
af901ca1 | 809 | RNum=0 - application had not returned any buffer to copy |
1da177e4 LT |
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 | } |