diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/isdn/hardware/eicon/di.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/isdn/hardware/eicon/di.c')
-rw-r--r-- | drivers/isdn/hardware/eicon/di.c | 835 |
1 files changed, 835 insertions, 0 deletions
diff --git a/drivers/isdn/hardware/eicon/di.c b/drivers/isdn/hardware/eicon/di.c new file mode 100644 index 000000000000..0617d7cabf06 --- /dev/null +++ b/drivers/isdn/hardware/eicon/di.c | |||
@@ -0,0 +1,835 @@ | |||
1 | |||
2 | /* | ||
3 | * | ||
4 | Copyright (c) Eicon Networks, 2002. | ||
5 | * | ||
6 | This source file is supplied for the use with | ||
7 | Eicon Networks range of DIVA Server Adapters. | ||
8 | * | ||
9 | Eicon File Revision : 2.1 | ||
10 | * | ||
11 | This program is free software; you can redistribute it and/or modify | ||
12 | it under the terms of the GNU General Public License as published by | ||
13 | the Free Software Foundation; either version 2, or (at your option) | ||
14 | any later version. | ||
15 | * | ||
16 | This program is distributed in the hope that it will be useful, | ||
17 | but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY | ||
18 | implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
19 | See the GNU General Public License for more details. | ||
20 | * | ||
21 | You should have received a copy of the GNU General Public License | ||
22 | along with this program; if not, write to the Free Software | ||
23 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "pc.h" | ||
28 | #include "pr_pc.h" | ||
29 | #include "di_defs.h" | ||
30 | #include "di.h" | ||
31 | #if !defined USE_EXTENDED_DEBUGS | ||
32 | #include "dimaint.h" | ||
33 | #else | ||
34 | #define dprintf | ||
35 | #endif | ||
36 | #include "io.h" | ||
37 | #include "dfifo.h" | ||
38 | #define PR_RAM ((struct pr_ram *)0) | ||
39 | #define RAM ((struct dual *)0) | ||
40 | /*------------------------------------------------------------------*/ | ||
41 | /* local function prototypes */ | ||
42 | /*------------------------------------------------------------------*/ | ||
43 | void pr_out(ADAPTER * a); | ||
44 | byte pr_dpc(ADAPTER * a); | ||
45 | static byte pr_ready(ADAPTER * a); | ||
46 | static byte isdn_rc(ADAPTER *, byte, byte, byte, word, dword, dword); | ||
47 | static byte isdn_ind(ADAPTER *, byte, byte, byte, PBUFFER *, byte, word); | ||
48 | /* ----------------------------------------------------------------- | ||
49 | Functions used for the extended XDI Debug | ||
50 | macros | ||
51 | global convergence counter (used by all adapters) | ||
52 | Look by the implementation part of the functions | ||
53 | about the parameters. | ||
54 | If you change the dubugging parameters, then you should update | ||
55 | the aididbg.doc in the IDI doc's. | ||
56 | ----------------------------------------------------------------- */ | ||
57 | #if defined(XDI_USE_XLOG) | ||
58 | #define XDI_A_NR(_x_) ((byte)(((ISDN_ADAPTER *)(_x_->io))->ANum)) | ||
59 | static void xdi_xlog (byte *msg, word code, int length); | ||
60 | static byte xdi_xlog_sec = 0; | ||
61 | #else | ||
62 | #define XDI_A_NR(_x_) ((byte)0) | ||
63 | #endif | ||
64 | static void xdi_xlog_rc_event (byte Adapter, | ||
65 | byte Id, byte Ch, byte Rc, byte cb, byte type); | ||
66 | static void xdi_xlog_request (byte Adapter, byte Id, | ||
67 | byte Ch, byte Req, byte type); | ||
68 | static void xdi_xlog_ind (byte Adapter, | ||
69 | byte Id, | ||
70 | byte Ch, | ||
71 | byte Ind, | ||
72 | byte rnr_valid, | ||
73 | byte rnr, | ||
74 | byte type); | ||
75 | /*------------------------------------------------------------------*/ | ||
76 | /* output function */ | ||
77 | /*------------------------------------------------------------------*/ | ||
78 | void pr_out(ADAPTER * a) | ||
79 | { | ||
80 | byte e_no; | ||
81 | ENTITY * this = NULL; | ||
82 | BUFFERS *X; | ||
83 | word length; | ||
84 | word i; | ||
85 | word clength; | ||
86 | REQ * ReqOut; | ||
87 | byte more; | ||
88 | byte ReadyCount; | ||
89 | byte ReqCount; | ||
90 | byte Id; | ||
91 | dtrc(dprintf("pr_out")); | ||
92 | /* while a request is pending ... */ | ||
93 | e_no = look_req(a); | ||
94 | if(!e_no) | ||
95 | { | ||
96 | dtrc(dprintf("no_req")); | ||
97 | return; | ||
98 | } | ||
99 | ReadyCount = pr_ready(a); | ||
100 | if(!ReadyCount) | ||
101 | { | ||
102 | dtrc(dprintf("not_ready")); | ||
103 | return; | ||
104 | } | ||
105 | ReqCount = 0; | ||
106 | while(e_no && ReadyCount) { | ||
107 | next_req(a); | ||
108 | this = entity_ptr(a, e_no); | ||
109 | #ifdef USE_EXTENDED_DEBUGS | ||
110 | if ( !this ) | ||
111 | { | ||
112 | DBG_FTL(("XDI: [%02x] !A%d ==> NULL entity ptr - try to ignore", | ||
113 | xdi_xlog_sec++, (int)((ISDN_ADAPTER *)a->io)->ANum)) | ||
114 | e_no = look_req(a) ; | ||
115 | ReadyCount-- ; | ||
116 | continue ; | ||
117 | } | ||
118 | { | ||
119 | DBG_TRC((">A%d Id=0x%x Req=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, this->Id, this->Req)) | ||
120 | } | ||
121 | #else | ||
122 | dbug(dprintf("out:Req=%x,Id=%x,Ch=%x",this->Req,this->Id,this->ReqCh)); | ||
123 | #endif | ||
124 | /* get address of next available request buffer */ | ||
125 | ReqOut = (REQ *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextReq)]; | ||
126 | #if defined(DIVA_ISTREAM) | ||
127 | if (!(a->tx_stream[this->Id] && | ||
128 | this->Req == N_DATA)) { | ||
129 | #endif | ||
130 | /* now copy the data from the current data buffer into the */ | ||
131 | /* adapters request buffer */ | ||
132 | length = 0; | ||
133 | i = this->XCurrent; | ||
134 | X = PTR_X(a,this); | ||
135 | while(i<this->XNum && length<270) { | ||
136 | clength = MIN((word)(270-length),X[i].PLength-this->XOffset); | ||
137 | a->ram_out_buffer(a, | ||
138 | &ReqOut->XBuffer.P[length], | ||
139 | PTR_P(a,this,&X[i].P[this->XOffset]), | ||
140 | clength); | ||
141 | length +=clength; | ||
142 | this->XOffset +=clength; | ||
143 | if(this->XOffset==X[i].PLength) { | ||
144 | this->XCurrent = (byte)++i; | ||
145 | this->XOffset = 0; | ||
146 | } | ||
147 | } | ||
148 | #if defined(DIVA_ISTREAM) | ||
149 | } else { /* Use CMA extension in order to transfer data to the card */ | ||
150 | i = this->XCurrent; | ||
151 | X = PTR_X(a,this); | ||
152 | while (i < this->XNum) { | ||
153 | diva_istream_write (a, | ||
154 | this->Id, | ||
155 | PTR_P(a,this,&X[i].P[0]), | ||
156 | X[i].PLength, | ||
157 | ((i+1) == this->XNum), | ||
158 | 0, 0); | ||
159 | this->XCurrent = (byte)++i; | ||
160 | } | ||
161 | length = 0; | ||
162 | } | ||
163 | #endif | ||
164 | a->ram_outw(a, &ReqOut->XBuffer.length, length); | ||
165 | a->ram_out(a, &ReqOut->ReqId, this->Id); | ||
166 | a->ram_out(a, &ReqOut->ReqCh, this->ReqCh); | ||
167 | /* if it's a specific request (no ASSIGN) ... */ | ||
168 | if(this->Id &0x1f) { | ||
169 | /* if buffers are left in the list of data buffers do */ | ||
170 | /* do chaining (LL_MDATA, N_MDATA) */ | ||
171 | this->More++; | ||
172 | if(i<this->XNum && this->MInd) { | ||
173 | xdi_xlog_request (XDI_A_NR(a), this->Id, this->ReqCh, this->MInd, | ||
174 | a->IdTypeTable[this->No]); | ||
175 | a->ram_out(a, &ReqOut->Req, this->MInd); | ||
176 | more = TRUE; | ||
177 | } | ||
178 | else { | ||
179 | xdi_xlog_request (XDI_A_NR(a), this->Id, this->ReqCh, this->Req, | ||
180 | a->IdTypeTable[this->No]); | ||
181 | this->More |=XMOREF; | ||
182 | a->ram_out(a, &ReqOut->Req, this->Req); | ||
183 | more = FALSE; | ||
184 | if (a->FlowControlIdTable[this->ReqCh] == this->Id) | ||
185 | a->FlowControlSkipTable[this->ReqCh] = TRUE; | ||
186 | /* | ||
187 | Note that remove request was sent to the card | ||
188 | */ | ||
189 | if (this->Req == REMOVE) { | ||
190 | a->misc_flags_table[e_no] |= DIVA_MISC_FLAGS_REMOVE_PENDING; | ||
191 | } | ||
192 | } | ||
193 | /* if we did chaining, this entity is put back into the */ | ||
194 | /* request queue */ | ||
195 | if(more) { | ||
196 | req_queue(a,this->No); | ||
197 | } | ||
198 | } | ||
199 | /* else it's a ASSIGN */ | ||
200 | else { | ||
201 | /* save the request code used for buffer chaining */ | ||
202 | this->MInd = 0; | ||
203 | if (this->Id==BLLC_ID) this->MInd = LL_MDATA; | ||
204 | if (this->Id==NL_ID || | ||
205 | this->Id==TASK_ID || | ||
206 | this->Id==MAN_ID | ||
207 | ) this->MInd = N_MDATA; | ||
208 | /* send the ASSIGN */ | ||
209 | a->IdTypeTable[this->No] = this->Id; | ||
210 | xdi_xlog_request (XDI_A_NR(a),this->Id,this->ReqCh,this->Req, this->Id); | ||
211 | this->More |=XMOREF; | ||
212 | a->ram_out(a, &ReqOut->Req, this->Req); | ||
213 | /* save the reference of the ASSIGN */ | ||
214 | assign_queue(a, this->No, a->ram_inw(a, &ReqOut->Reference)); | ||
215 | } | ||
216 | a->ram_outw(a, &PR_RAM->NextReq, a->ram_inw(a, &ReqOut->next)); | ||
217 | ReadyCount--; | ||
218 | ReqCount++; | ||
219 | e_no = look_req(a); | ||
220 | } | ||
221 | /* send the filled request buffers to the ISDN adapter */ | ||
222 | a->ram_out(a, &PR_RAM->ReqInput, | ||
223 | (byte)(a->ram_in(a, &PR_RAM->ReqInput) + ReqCount)); | ||
224 | /* if it is a 'unreturncoded' UREMOVE request, remove the */ | ||
225 | /* Id from our table after sending the request */ | ||
226 | if(this && (this->Req==UREMOVE) && this->Id) { | ||
227 | Id = this->Id; | ||
228 | e_no = a->IdTable[Id]; | ||
229 | free_entity(a, e_no); | ||
230 | for (i = 0; i < 256; i++) | ||
231 | { | ||
232 | if (a->FlowControlIdTable[i] == Id) | ||
233 | a->FlowControlIdTable[i] = 0; | ||
234 | } | ||
235 | a->IdTable[Id] = 0; | ||
236 | this->Id = 0; | ||
237 | } | ||
238 | } | ||
239 | static byte pr_ready(ADAPTER * a) | ||
240 | { | ||
241 | byte ReadyCount; | ||
242 | ReadyCount = (byte)(a->ram_in(a, &PR_RAM->ReqOutput) - | ||
243 | a->ram_in(a, &PR_RAM->ReqInput)); | ||
244 | if(!ReadyCount) { | ||
245 | if(!a->ReadyInt) { | ||
246 | a->ram_inc(a, &PR_RAM->ReadyInt); | ||
247 | a->ReadyInt++; | ||
248 | } | ||
249 | } | ||
250 | return ReadyCount; | ||
251 | } | ||
252 | /*------------------------------------------------------------------*/ | ||
253 | /* isdn interrupt handler */ | ||
254 | /*------------------------------------------------------------------*/ | ||
255 | byte pr_dpc(ADAPTER * a) | ||
256 | { | ||
257 | byte Count; | ||
258 | RC * RcIn; | ||
259 | IND * IndIn; | ||
260 | byte c; | ||
261 | byte RNRId; | ||
262 | byte Rc; | ||
263 | byte Ind; | ||
264 | /* if return codes are available ... */ | ||
265 | if((Count = a->ram_in(a, &PR_RAM->RcOutput)) != 0) { | ||
266 | dtrc(dprintf("#Rc=%x",Count)); | ||
267 | /* get the buffer address of the first return code */ | ||
268 | RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextRc)]; | ||
269 | /* for all return codes do ... */ | ||
270 | while(Count--) { | ||
271 | if((Rc=a->ram_in(a, &RcIn->Rc)) != 0) { | ||
272 | dword tmp[2]; | ||
273 | /* | ||
274 | Get extended information, associated with return code | ||
275 | */ | ||
276 | a->ram_in_buffer(a, | ||
277 | &RcIn->Reserved2[0], | ||
278 | (byte*)&tmp[0], | ||
279 | 8); | ||
280 | /* call return code handler, if it is not our return code */ | ||
281 | /* the handler returns 2 */ | ||
282 | /* for all return codes we process, we clear the Rc field */ | ||
283 | isdn_rc(a, | ||
284 | Rc, | ||
285 | a->ram_in(a, &RcIn->RcId), | ||
286 | a->ram_in(a, &RcIn->RcCh), | ||
287 | a->ram_inw(a, &RcIn->Reference), | ||
288 | tmp[0], /* type of extended informtion */ | ||
289 | tmp[1]); /* extended information */ | ||
290 | a->ram_out(a, &RcIn->Rc, 0); | ||
291 | } | ||
292 | /* get buffer address of next return code */ | ||
293 | RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &RcIn->next)]; | ||
294 | } | ||
295 | /* clear all return codes (no chaining!) */ | ||
296 | a->ram_out(a, &PR_RAM->RcOutput ,0); | ||
297 | /* call output function */ | ||
298 | pr_out(a); | ||
299 | } | ||
300 | /* clear RNR flag */ | ||
301 | RNRId = 0; | ||
302 | /* if indications are available ... */ | ||
303 | if((Count = a->ram_in(a, &PR_RAM->IndOutput)) != 0) { | ||
304 | dtrc(dprintf("#Ind=%x",Count)); | ||
305 | /* get the buffer address of the first indication */ | ||
306 | IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextInd)]; | ||
307 | /* for all indications do ... */ | ||
308 | while(Count--) { | ||
309 | /* if the application marks an indication as RNR, all */ | ||
310 | /* indications from the same Id delivered in this interrupt */ | ||
311 | /* are marked RNR */ | ||
312 | if(RNRId && RNRId==a->ram_in(a, &IndIn->IndId)) { | ||
313 | a->ram_out(a, &IndIn->Ind, 0); | ||
314 | a->ram_out(a, &IndIn->RNR, TRUE); | ||
315 | } | ||
316 | else { | ||
317 | Ind = a->ram_in(a, &IndIn->Ind); | ||
318 | if(Ind) { | ||
319 | RNRId = 0; | ||
320 | /* call indication handler, a return value of 2 means chain */ | ||
321 | /* a return value of 1 means RNR */ | ||
322 | /* for all indications we process, we clear the Ind field */ | ||
323 | c = isdn_ind(a, | ||
324 | Ind, | ||
325 | a->ram_in(a, &IndIn->IndId), | ||
326 | a->ram_in(a, &IndIn->IndCh), | ||
327 | &IndIn->RBuffer, | ||
328 | a->ram_in(a, &IndIn->MInd), | ||
329 | a->ram_inw(a, &IndIn->MLength)); | ||
330 | if(c==1) { | ||
331 | dtrc(dprintf("RNR")); | ||
332 | a->ram_out(a, &IndIn->Ind, 0); | ||
333 | RNRId = a->ram_in(a, &IndIn->IndId); | ||
334 | a->ram_out(a, &IndIn->RNR, TRUE); | ||
335 | } | ||
336 | } | ||
337 | } | ||
338 | /* get buffer address of next indication */ | ||
339 | IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &IndIn->next)]; | ||
340 | } | ||
341 | a->ram_out(a, &PR_RAM->IndOutput, 0); | ||
342 | } | ||
343 | return FALSE; | ||
344 | } | ||
345 | byte scom_test_int(ADAPTER * a) | ||
346 | { | ||
347 | return a->ram_in(a,(void *)0x3fe); | ||
348 | } | ||
349 | void scom_clear_int(ADAPTER * a) | ||
350 | { | ||
351 | a->ram_out(a,(void *)0x3fe,0); | ||
352 | } | ||
353 | /*------------------------------------------------------------------*/ | ||
354 | /* return code handler */ | ||
355 | /*------------------------------------------------------------------*/ | ||
356 | byte isdn_rc(ADAPTER * a, | ||
357 | byte Rc, | ||
358 | byte Id, | ||
359 | byte Ch, | ||
360 | word Ref, | ||
361 | dword extended_info_type, | ||
362 | dword extended_info) | ||
363 | { | ||
364 | ENTITY * this; | ||
365 | byte e_no; | ||
366 | word i; | ||
367 | int cancel_rc; | ||
368 | #ifdef USE_EXTENDED_DEBUGS | ||
369 | { | ||
370 | DBG_TRC(("<A%d Id=0x%x Rc=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, Id, Rc)) | ||
371 | } | ||
372 | #else | ||
373 | dbug(dprintf("isdn_rc(Rc=%x,Id=%x,Ch=%x)",Rc,Id,Ch)); | ||
374 | #endif | ||
375 | /* check for ready interrupt */ | ||
376 | if(Rc==READY_INT) { | ||
377 | xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 0, 0); | ||
378 | if(a->ReadyInt) { | ||
379 | a->ReadyInt--; | ||
380 | return 0; | ||
381 | } | ||
382 | return 2; | ||
383 | } | ||
384 | /* if we know this Id ... */ | ||
385 | e_no = a->IdTable[Id]; | ||
386 | if(e_no) { | ||
387 | this = entity_ptr(a,e_no); | ||
388 | xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 0, a->IdTypeTable[this->No]); | ||
389 | this->RcCh = Ch; | ||
390 | /* if it is a return code to a REMOVE request, remove the */ | ||
391 | /* Id from our table */ | ||
392 | if ((a->misc_flags_table[e_no] & DIVA_MISC_FLAGS_REMOVE_PENDING) && | ||
393 | (Rc==OK)) { | ||
394 | if (a->IdTypeTable[e_no] == NL_ID) { | ||
395 | if (a->RcExtensionSupported && | ||
396 | (extended_info_type != DIVA_RC_TYPE_REMOVE_COMPLETE)) { | ||
397 | dtrc(dprintf("XDI: N-REMOVE, A(%02x) Id:%02x, ignore RC=OK", | ||
398 | XDI_A_NR(a),Id)); | ||
399 | return (0); | ||
400 | } | ||
401 | if (extended_info_type == DIVA_RC_TYPE_REMOVE_COMPLETE) | ||
402 | a->RcExtensionSupported = TRUE; | ||
403 | } | ||
404 | a->misc_flags_table[e_no] &= ~DIVA_MISC_FLAGS_REMOVE_PENDING; | ||
405 | a->misc_flags_table[e_no] &= ~DIVA_MISC_FLAGS_NO_RC_CANCELLING; | ||
406 | free_entity(a, e_no); | ||
407 | for (i = 0; i < 256; i++) | ||
408 | { | ||
409 | if (a->FlowControlIdTable[i] == Id) | ||
410 | a->FlowControlIdTable[i] = 0; | ||
411 | } | ||
412 | a->IdTable[Id] = 0; | ||
413 | this->Id = 0; | ||
414 | /* --------------------------------------------------------------- | ||
415 | If we send N_DISC or N_DISK_ACK after we have received OK_FC | ||
416 | then the card will respond with OK_FC and later with RC==OK. | ||
417 | If we send N_REMOVE in this state we will receive only RC==OK | ||
418 | This will create the state in that the XDI is waiting for the | ||
419 | additional RC and does not delivery the RC to the client. This | ||
420 | code corrects the counter of outstanding RC's in this case. | ||
421 | --------------------------------------------------------------- */ | ||
422 | if ((this->More & XMOREC) > 1) { | ||
423 | this->More &= ~XMOREC; | ||
424 | this->More |= 1; | ||
425 | dtrc(dprintf("XDI: correct MORE on REMOVE A(%02x) Id:%02x", | ||
426 | XDI_A_NR(a),Id)); | ||
427 | } | ||
428 | } | ||
429 | if (Rc==OK_FC) { | ||
430 | a->FlowControlIdTable[Ch] = Id; | ||
431 | a->FlowControlSkipTable[Ch] = FALSE; | ||
432 | this->Rc = Rc; | ||
433 | this->More &= ~(XBUSY | XMOREC); | ||
434 | this->complete=0xff; | ||
435 | xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]); | ||
436 | CALLBACK(a, this); | ||
437 | return 0; | ||
438 | } | ||
439 | /* | ||
440 | New protocol code sends return codes that comes from release | ||
441 | of flow control condition marked with DIVA_RC_TYPE_OK_FC extended | ||
442 | information element type. | ||
443 | If like return code arrives then application is able to process | ||
444 | all return codes self and XDI should not cances return codes. | ||
445 | This return code does not decrement XMOREC partial return code | ||
446 | counter due to fact that it was no request for this return code, | ||
447 | also XMOREC was not incremented. | ||
448 | */ | ||
449 | if (extended_info_type == DIVA_RC_TYPE_OK_FC) { | ||
450 | a->misc_flags_table[e_no] |= DIVA_MISC_FLAGS_NO_RC_CANCELLING; | ||
451 | this->Rc = Rc; | ||
452 | this->complete=0xff; | ||
453 | xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]); | ||
454 | DBG_TRC(("XDI OK_FC A(%02x) Id:%02x Ch:%02x Rc:%02x", | ||
455 | XDI_A_NR(a), Id, Ch, Rc)) | ||
456 | CALLBACK(a, this); | ||
457 | return 0; | ||
458 | } | ||
459 | cancel_rc = !(a->misc_flags_table[e_no] & DIVA_MISC_FLAGS_NO_RC_CANCELLING); | ||
460 | if (cancel_rc && (a->FlowControlIdTable[Ch] == Id)) | ||
461 | { | ||
462 | a->FlowControlIdTable[Ch] = 0; | ||
463 | if ((Rc != OK) || !a->FlowControlSkipTable[Ch]) | ||
464 | { | ||
465 | this->Rc = Rc; | ||
466 | if (Ch == this->ReqCh) | ||
467 | { | ||
468 | this->More &=~(XBUSY | XMOREC); | ||
469 | this->complete=0xff; | ||
470 | } | ||
471 | xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]); | ||
472 | CALLBACK(a, this); | ||
473 | } | ||
474 | return 0; | ||
475 | } | ||
476 | if (this->More &XMOREC) | ||
477 | this->More--; | ||
478 | /* call the application callback function */ | ||
479 | if (((!cancel_rc) || (this->More & XMOREF)) && !(this->More & XMOREC)) { | ||
480 | this->Rc = Rc; | ||
481 | this->More &=~XBUSY; | ||
482 | this->complete=0xff; | ||
483 | xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 1, a->IdTypeTable[this->No]); | ||
484 | CALLBACK(a, this); | ||
485 | } | ||
486 | return 0; | ||
487 | } | ||
488 | /* if it's an ASSIGN return code check if it's a return */ | ||
489 | /* code to an ASSIGN request from us */ | ||
490 | if((Rc &0xf0)==ASSIGN_RC) { | ||
491 | e_no = get_assign(a, Ref); | ||
492 | if(e_no) { | ||
493 | this = entity_ptr(a,e_no); | ||
494 | this->Id = Id; | ||
495 | xdi_xlog_rc_event (XDI_A_NR(a), Id, Ch, Rc, 2, a->IdTypeTable[this->No]); | ||
496 | /* call the application callback function */ | ||
497 | this->Rc = Rc; | ||
498 | this->More &=~XBUSY; | ||
499 | this->complete=0xff; | ||
500 | #if defined(DIVA_ISTREAM) /* { */ | ||
501 | if ((Rc == ASSIGN_OK) && a->ram_offset && | ||
502 | (a->IdTypeTable[this->No] == NL_ID) && | ||
503 | ((extended_info_type == DIVA_RC_TYPE_RX_DMA) || | ||
504 | (extended_info_type == DIVA_RC_TYPE_CMA_PTR)) && | ||
505 | extended_info) { | ||
506 | dword offset = (*(a->ram_offset)) (a); | ||
507 | dword tmp[2]; | ||
508 | extended_info -= offset; | ||
509 | #ifdef PLATFORM_GT_32BIT | ||
510 | a->ram_in_dw(a, (void*)ULongToPtr(extended_info), (dword*)&tmp[0], 2); | ||
511 | #else | ||
512 | a->ram_in_dw(a, (void*)extended_info, (dword*)&tmp[0], 2); | ||
513 | #endif | ||
514 | a->tx_stream[Id] = tmp[0]; | ||
515 | a->rx_stream[Id] = tmp[1]; | ||
516 | if (extended_info_type == DIVA_RC_TYPE_RX_DMA) { | ||
517 | DBG_TRC(("Id=0x%x RxDMA=%08x:%08x", | ||
518 | Id, a->tx_stream[Id], a->rx_stream[Id])) | ||
519 | a->misc_flags_table[this->No] |= DIVA_MISC_FLAGS_RX_DMA; | ||
520 | } else { | ||
521 | DBG_TRC(("Id=0x%x CMA=%08x:%08x", | ||
522 | Id, a->tx_stream[Id], a->rx_stream[Id])) | ||
523 | a->misc_flags_table[this->No] &= ~DIVA_MISC_FLAGS_RX_DMA; | ||
524 | a->rx_pos[Id] = 0; | ||
525 | a->rx_stream[Id] -= offset; | ||
526 | } | ||
527 | a->tx_pos[Id] = 0; | ||
528 | a->tx_stream[Id] -= offset; | ||
529 | } else { | ||
530 | a->tx_stream[Id] = 0; | ||
531 | a->rx_stream[Id] = 0; | ||
532 | a->misc_flags_table[this->No] &= ~DIVA_MISC_FLAGS_RX_DMA; | ||
533 | } | ||
534 | #endif /* } */ | ||
535 | CALLBACK(a, this); | ||
536 | if(Rc==ASSIGN_OK) { | ||
537 | a->IdTable[Id] = e_no; | ||
538 | } | ||
539 | else | ||
540 | { | ||
541 | free_entity(a, e_no); | ||
542 | for (i = 0; i < 256; i++) | ||
543 | { | ||
544 | if (a->FlowControlIdTable[i] == Id) | ||
545 | a->FlowControlIdTable[i] = 0; | ||
546 | } | ||
547 | a->IdTable[Id] = 0; | ||
548 | this->Id = 0; | ||
549 | } | ||
550 | return 1; | ||
551 | } | ||
552 | } | ||
553 | return 2; | ||
554 | } | ||
555 | /*------------------------------------------------------------------*/ | ||
556 | /* indication handler */ | ||
557 | /*------------------------------------------------------------------*/ | ||
558 | byte isdn_ind(ADAPTER * a, | ||
559 | byte Ind, | ||
560 | byte Id, | ||
561 | byte Ch, | ||
562 | PBUFFER * RBuffer, | ||
563 | byte MInd, | ||
564 | word MLength) | ||
565 | { | ||
566 | ENTITY * this; | ||
567 | word clength; | ||
568 | word offset; | ||
569 | BUFFERS *R; | ||
570 | byte* cma = NULL; | ||
571 | #ifdef USE_EXTENDED_DEBUGS | ||
572 | { | ||
573 | DBG_TRC(("<A%d Id=0x%x Ind=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, Id, Ind)) | ||
574 | } | ||
575 | #else | ||
576 | dbug(dprintf("isdn_ind(Ind=%x,Id=%x,Ch=%x)",Ind,Id,Ch)); | ||
577 | #endif | ||
578 | if(a->IdTable[Id]) { | ||
579 | this = entity_ptr(a,a->IdTable[Id]); | ||
580 | this->IndCh = Ch; | ||
581 | xdi_xlog_ind (XDI_A_NR(a), Id, Ch, Ind, | ||
582 | 0/* rnr_valid */, 0 /* rnr */, a->IdTypeTable[this->No]); | ||
583 | /* if the Receive More flag is not yet set, this is the */ | ||
584 | /* first buffer of the packet */ | ||
585 | if(this->RCurrent==0xff) { | ||
586 | /* check for receive buffer chaining */ | ||
587 | if(Ind==this->MInd) { | ||
588 | this->complete = 0; | ||
589 | this->Ind = MInd; | ||
590 | } | ||
591 | else { | ||
592 | this->complete = 1; | ||
593 | this->Ind = Ind; | ||
594 | } | ||
595 | /* call the application callback function for the receive */ | ||
596 | /* look ahead */ | ||
597 | this->RLength = MLength; | ||
598 | #if defined(DIVA_ISTREAM) | ||
599 | if ((a->rx_stream[this->Id] || | ||
600 | (a->misc_flags_table[this->No] & DIVA_MISC_FLAGS_RX_DMA)) && | ||
601 | ((Ind == N_DATA) || | ||
602 | (a->protocol_capabilities & PROTCAP_CMA_ALLPR))) { | ||
603 | PISDN_ADAPTER IoAdapter = (PISDN_ADAPTER)a->io ; | ||
604 | if (a->misc_flags_table[this->No] & DIVA_MISC_FLAGS_RX_DMA) { | ||
605 | #if defined(DIVA_IDI_RX_DMA) | ||
606 | dword d; | ||
607 | diva_get_dma_map_entry (\ | ||
608 | (struct _diva_dma_map_entry*)IoAdapter->dma_map, | ||
609 | (int)a->rx_stream[this->Id], (void**)&cma, &d); | ||
610 | #else | ||
611 | cma = &a->stream_buffer[0]; | ||
612 | cma[0] = cma[1] = cma[2] = cma[3] = 0; | ||
613 | #endif | ||
614 | this->RLength = MLength = (word)*(dword*)cma; | ||
615 | cma += 4; | ||
616 | } else { | ||
617 | int final = 0; | ||
618 | cma = &a->stream_buffer[0]; | ||
619 | this->RLength = MLength = (word)diva_istream_read (a, | ||
620 | Id, | ||
621 | cma, | ||
622 | sizeof(a->stream_buffer), | ||
623 | &final, NULL, NULL); | ||
624 | } | ||
625 | IoAdapter->RBuffer.length = MIN(MLength, 270); | ||
626 | if (IoAdapter->RBuffer.length != MLength) { | ||
627 | this->complete = 0; | ||
628 | } else { | ||
629 | this->complete = 1; | ||
630 | } | ||
631 | memcpy (IoAdapter->RBuffer.P, cma, IoAdapter->RBuffer.length) ; | ||
632 | this->RBuffer = (DBUFFER *)&IoAdapter->RBuffer ; | ||
633 | } | ||
634 | #endif | ||
635 | if (!cma) { | ||
636 | a->ram_look_ahead(a, RBuffer, this); | ||
637 | } | ||
638 | this->RNum = 0; | ||
639 | CALLBACK(a, this); | ||
640 | /* map entity ptr, selector could be re-mapped by call to */ | ||
641 | /* IDI from within callback */ | ||
642 | this = entity_ptr(a,a->IdTable[Id]); | ||
643 | xdi_xlog_ind (XDI_A_NR(a), Id, Ch, Ind, | ||
644 | 1/* rnr_valid */, this->RNR/* rnr */, a->IdTypeTable[this->No]); | ||
645 | /* check for RNR */ | ||
646 | if(this->RNR==1) { | ||
647 | this->RNR = 0; | ||
648 | return 1; | ||
649 | } | ||
650 | /* if no buffers are provided by the application, the */ | ||
651 | /* application want to copy the data itself including */ | ||
652 | /* N_MDATA/LL_MDATA chaining */ | ||
653 | if(!this->RNR && !this->RNum) { | ||
654 | xdi_xlog_ind (XDI_A_NR(a), Id, Ch, Ind, | ||
655 | 2/* rnr_valid */, 0/* rnr */, a->IdTypeTable[this->No]); | ||
656 | return 0; | ||
657 | } | ||
658 | /* if there is no RNR, set the More flag */ | ||
659 | this->RCurrent = 0; | ||
660 | this->ROffset = 0; | ||
661 | } | ||
662 | if(this->RNR==2) { | ||
663 | if(Ind!=this->MInd) { | ||
664 | this->RCurrent = 0xff; | ||
665 | this->RNR = 0; | ||
666 | } | ||
667 | return 0; | ||
668 | } | ||
669 | /* if we have received buffers from the application, copy */ | ||
670 | /* the data into these buffers */ | ||
671 | offset = 0; | ||
672 | R = PTR_R(a,this); | ||
673 | do { | ||
674 | if(this->ROffset==R[this->RCurrent].PLength) { | ||
675 | this->ROffset = 0; | ||
676 | this->RCurrent++; | ||
677 | } | ||
678 | if (cma) { | ||
679 | clength = MIN(MLength, R[this->RCurrent].PLength-this->ROffset); | ||
680 | } else { | ||
681 | clength = MIN(a->ram_inw(a, &RBuffer->length)-offset, | ||
682 | R[this->RCurrent].PLength-this->ROffset); | ||
683 | } | ||
684 | if(R[this->RCurrent].P) { | ||
685 | if (cma) { | ||
686 | memcpy (PTR_P(a,this,&R[this->RCurrent].P[this->ROffset]), | ||
687 | &cma[offset], | ||
688 | clength); | ||
689 | } else { | ||
690 | a->ram_in_buffer(a, | ||
691 | &RBuffer->P[offset], | ||
692 | PTR_P(a,this,&R[this->RCurrent].P[this->ROffset]), | ||
693 | clength); | ||
694 | } | ||
695 | } | ||
696 | offset +=clength; | ||
697 | this->ROffset +=clength; | ||
698 | if (cma) { | ||
699 | if (offset >= MLength) { | ||
700 | break; | ||
701 | } | ||
702 | continue; | ||
703 | } | ||
704 | } while(offset<(a->ram_inw(a, &RBuffer->length))); | ||
705 | /* if it's the last buffer of the packet, call the */ | ||
706 | /* application callback function for the receive complete */ | ||
707 | /* call */ | ||
708 | if(Ind!=this->MInd) { | ||
709 | R[this->RCurrent].PLength = this->ROffset; | ||
710 | if(this->ROffset) this->RCurrent++; | ||
711 | this->RNum = this->RCurrent; | ||
712 | this->RCurrent = 0xff; | ||
713 | this->Ind = Ind; | ||
714 | this->complete = 2; | ||
715 | xdi_xlog_ind (XDI_A_NR(a), Id, Ch, Ind, | ||
716 | 3/* rnr_valid */, 0/* rnr */, a->IdTypeTable[this->No]); | ||
717 | CALLBACK(a, this); | ||
718 | } | ||
719 | return 0; | ||
720 | } | ||
721 | return 2; | ||
722 | } | ||
723 | #if defined(XDI_USE_XLOG) | ||
724 | /* ----------------------------------------------------------- | ||
725 | This function works in the same way as xlog on the | ||
726 | active board | ||
727 | ----------------------------------------------------------- */ | ||
728 | static void xdi_xlog (byte *msg, word code, int length) { | ||
729 | xdi_dbg_xlog ("\x00\x02", msg, code, length); | ||
730 | } | ||
731 | #endif | ||
732 | /* ----------------------------------------------------------- | ||
733 | This function writes the information about the Return Code | ||
734 | processing in the trace buffer. Trace ID is 221. | ||
735 | INPUT: | ||
736 | Adapter - system unicue adapter number (0 ... 255) | ||
737 | Id - Id of the entity that had sent this return code | ||
738 | Ch - Channel of the entity that had sent this return code | ||
739 | Rc - return code value | ||
740 | cb: (0...2) | ||
741 | switch (cb) { | ||
742 | case 0: printf ("DELIVERY"); break; | ||
743 | case 1: printf ("CALLBACK"); break; | ||
744 | case 2: printf ("ASSIGN"); break; | ||
745 | } | ||
746 | DELIVERY - have entered isdn_rc with this RC | ||
747 | CALLBACK - about to make callback to the application | ||
748 | for this RC | ||
749 | ASSIGN - about to make callback for RC that is result | ||
750 | of ASSIGN request. It is no DELIVERY message | ||
751 | before of this message | ||
752 | type - the Id that was sent by the ASSIGN of this entity. | ||
753 | This should be global Id like NL_ID, DSIG_ID, MAN_ID. | ||
754 | An unknown Id will cause "?-" in the front of the request. | ||
755 | In this case the log.c is to be extended. | ||
756 | ----------------------------------------------------------- */ | ||
757 | static void xdi_xlog_rc_event (byte Adapter, | ||
758 | byte Id, byte Ch, byte Rc, byte cb, byte type) { | ||
759 | #if defined(XDI_USE_XLOG) | ||
760 | word LogInfo[4]; | ||
761 | PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8))); | ||
762 | PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8))); | ||
763 | PUT_WORD(&LogInfo[2], ((word)Rc | (word)(type << 8))); | ||
764 | PUT_WORD(&LogInfo[3], cb); | ||
765 | xdi_xlog ((byte*)&LogInfo[0], 221, sizeof(LogInfo)); | ||
766 | #endif | ||
767 | } | ||
768 | /* ------------------------------------------------------------------------ | ||
769 | This function writes the information about the request processing | ||
770 | in the trace buffer. Trace ID is 220. | ||
771 | INPUT: | ||
772 | Adapter - system unicue adapter number (0 ... 255) | ||
773 | Id - Id of the entity that had sent this request | ||
774 | Ch - Channel of the entity that had sent this request | ||
775 | Req - Code of the request | ||
776 | type - the Id that was sent by the ASSIGN of this entity. | ||
777 | This should be global Id like NL_ID, DSIG_ID, MAN_ID. | ||
778 | An unknown Id will cause "?-" in the front of the request. | ||
779 | In this case the log.c is to be extended. | ||
780 | ------------------------------------------------------------------------ */ | ||
781 | static void xdi_xlog_request (byte Adapter, byte Id, | ||
782 | byte Ch, byte Req, byte type) { | ||
783 | #if defined(XDI_USE_XLOG) | ||
784 | word LogInfo[3]; | ||
785 | PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8))); | ||
786 | PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8))); | ||
787 | PUT_WORD(&LogInfo[2], ((word)Req | (word)(type << 8))); | ||
788 | xdi_xlog ((byte*)&LogInfo[0], 220, sizeof(LogInfo)); | ||
789 | #endif | ||
790 | } | ||
791 | /* ------------------------------------------------------------------------ | ||
792 | This function writes the information about the indication processing | ||
793 | in the trace buffer. Trace ID is 222. | ||
794 | INPUT: | ||
795 | Adapter - system unicue adapter number (0 ... 255) | ||
796 | Id - Id of the entity that had sent this indication | ||
797 | Ch - Channel of the entity that had sent this indication | ||
798 | Ind - Code of the indication | ||
799 | rnr_valid: (0 .. 3) supported | ||
800 | switch (rnr_valid) { | ||
801 | case 0: printf ("DELIVERY"); break; | ||
802 | case 1: printf ("RNR=%d", rnr); | ||
803 | case 2: printf ("RNum=0"); | ||
804 | case 3: printf ("COMPLETE"); | ||
805 | } | ||
806 | DELIVERY - indication entered isdn_rc function | ||
807 | RNR=... - application had returned RNR=... after the | ||
808 | look ahead callback | ||
809 | RNum=0 - aplication had not returned any buffer to copy | ||
810 | this indication and will copy it self | ||
811 | COMPLETE - XDI had copied the data to the buffers provided | ||
812 | bu the application and is about to issue the | ||
813 | final callback | ||
814 | rnr: Look case 1 of the rnr_valid | ||
815 | type: the Id that was sent by the ASSIGN of this entity. This should | ||
816 | be global Id like NL_ID, DSIG_ID, MAN_ID. An unknown Id will | ||
817 | cause "?-" in the front of the request. In this case the | ||
818 | log.c is to be extended. | ||
819 | ------------------------------------------------------------------------ */ | ||
820 | static void xdi_xlog_ind (byte Adapter, | ||
821 | byte Id, | ||
822 | byte Ch, | ||
823 | byte Ind, | ||
824 | byte rnr_valid, | ||
825 | byte rnr, | ||
826 | byte type) { | ||
827 | #if defined(XDI_USE_XLOG) | ||
828 | word LogInfo[4]; | ||
829 | PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8))); | ||
830 | PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8))); | ||
831 | PUT_WORD(&LogInfo[2], ((word)Ind | (word)(type << 8))); | ||
832 | PUT_WORD(&LogInfo[3], ((word)rnr | (word)(rnr_valid << 8))); | ||
833 | xdi_xlog ((byte*)&LogInfo[0], 222, sizeof(LogInfo)); | ||
834 | #endif | ||
835 | } | ||