File: /usr/src/linux/drivers/isdn/eicon/eicon_io.c
1 /* $Id: eicon_io.c,v 1.13.6.1 2001/02/16 09:09:50 armin Exp $
2 *
3 * ISDN low-level module for Eicon active ISDN-Cards.
4 * Code for communicating with hardware.
5 *
6 * Copyright 1999,2000 by Armin Schindler (mac@melware.de)
7 * Copyright 1999,2000 Cytronics & Melware (info@melware.de)
8 *
9 * Thanks to Eicon Networks for
10 * documents, informations and hardware.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
26 */
27
28
29 #include <linux/config.h>
30 #include "eicon.h"
31 #include "uxio.h"
32
33 void
34 eicon_io_rcv_dispatch(eicon_card *ccard) {
35 ulong flags;
36 struct sk_buff *skb, *skb2, *skb_new;
37 eicon_IND *ind, *ind2, *ind_new;
38 eicon_chan *chan;
39
40 if (!ccard) {
41 eicon_log(ccard, 1, "eicon_err: NULL card in rcv_dispatch !\n");
42 return;
43 }
44
45 while((skb = skb_dequeue(&ccard->rcvq))) {
46 ind = (eicon_IND *)skb->data;
47
48 spin_lock_irqsave(&eicon_lock, flags);
49 if ((chan = ccard->IdTable[ind->IndId]) == NULL) {
50 spin_unlock_irqrestore(&eicon_lock, flags);
51 if (DebugVar & 1) {
52 switch(ind->Ind) {
53 case N_DISC_ACK:
54 /* doesn't matter if this happens */
55 break;
56 default:
57 eicon_log(ccard, 1, "idi: Indication for unknown channel Ind=%d Id=%x\n", ind->Ind, ind->IndId);
58 eicon_log(ccard, 1, "idi_hdl: Ch??: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
59 ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
60 }
61 }
62 dev_kfree_skb(skb);
63 continue;
64 }
65 spin_unlock_irqrestore(&eicon_lock, flags);
66
67 if (chan->e.complete) { /* check for rec-buffer chaining */
68 if (ind->MLength == ind->RBuffer.length) {
69 chan->e.complete = 1;
70 idi_handle_ind(ccard, skb);
71 continue;
72 }
73 else {
74 chan->e.complete = 0;
75 ind->Ind = ind->MInd;
76 skb_queue_tail(&chan->e.R, skb);
77 continue;
78 }
79 }
80 else {
81 if (!(skb2 = skb_dequeue(&chan->e.R))) {
82 chan->e.complete = 1;
83 eicon_log(ccard, 1, "eicon: buffer incomplete, but 0 in queue\n");
84 dev_kfree_skb(skb);
85 continue;
86 }
87 ind2 = (eicon_IND *)skb2->data;
88 skb_new = alloc_skb(((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length),
89 GFP_ATOMIC);
90 if (!skb_new) {
91 eicon_log(ccard, 1, "eicon_io: skb_alloc failed in rcv_dispatch()\n");
92 dev_kfree_skb(skb);
93 dev_kfree_skb(skb2);
94 continue;
95 }
96 ind_new = (eicon_IND *)skb_put(skb_new,
97 ((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length));
98 ind_new->Ind = ind2->Ind;
99 ind_new->IndId = ind2->IndId;
100 ind_new->IndCh = ind2->IndCh;
101 ind_new->MInd = ind2->MInd;
102 ind_new->MLength = ind2->MLength;
103 ind_new->RBuffer.length = ind2->RBuffer.length + ind->RBuffer.length;
104 memcpy(&ind_new->RBuffer.P, &ind2->RBuffer.P, ind2->RBuffer.length);
105 memcpy((&ind_new->RBuffer.P)+ind2->RBuffer.length, &ind->RBuffer.P, ind->RBuffer.length);
106 dev_kfree_skb(skb);
107 dev_kfree_skb(skb2);
108 if (ind->MLength == ind->RBuffer.length) {
109 chan->e.complete = 2;
110 idi_handle_ind(ccard, skb_new);
111 continue;
112 }
113 else {
114 chan->e.complete = 0;
115 skb_queue_tail(&chan->e.R, skb_new);
116 continue;
117 }
118 }
119 }
120 }
121
122 void
123 eicon_io_ack_dispatch(eicon_card *ccard) {
124 struct sk_buff *skb;
125
126 if (!ccard) {
127 eicon_log(ccard, 1, "eicon_err: NULL card in ack_dispatch!\n");
128 return;
129 }
130 while((skb = skb_dequeue(&ccard->rackq))) {
131 idi_handle_ack(ccard, skb);
132 }
133 }
134
135
136 /*
137 * IO-Functions for ISA cards
138 */
139
140 u8 ram_inb(eicon_card *card, void *adr) {
141 u32 addr = (u32) adr;
142
143 return(readb(addr));
144 }
145
146 u16 ram_inw(eicon_card *card, void *adr) {
147 u32 addr = (u32) adr;
148
149 return(readw(addr));
150 }
151
152 void ram_outb(eicon_card *card, void *adr, u8 data) {
153 u32 addr = (u32) adr;
154
155 writeb(data, addr);
156 }
157
158 void ram_outw(eicon_card *card, void *adr , u16 data) {
159 u32 addr = (u32) adr;
160
161 writew(data, addr);
162 }
163
164 void ram_copyfromcard(eicon_card *card, void *adrto, void *adr, int len) {
165 memcpy_fromio(adrto, adr, len);
166 }
167
168 void ram_copytocard(eicon_card *card, void *adrto, void *adr, int len) {
169 memcpy_toio(adrto, adr, len);
170 }
171
172
173 #ifdef CONFIG_ISDN_DRV_EICON_PCI
174 /*
175 * IDI-Callback function
176 */
177 void
178 eicon_idi_callback(ENTITY *de)
179 {
180 eicon_card *ccard = (eicon_card *)de->R;
181 struct sk_buff *skb;
182 eicon_RC *ack;
183 eicon_IND *ind;
184 int len = 0;
185
186 if (de->complete == 255) {
187 /* Return Code */
188 skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
189 if (!skb) {
190 eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _idi_callback()\n");
191 } else {
192 ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
193 ack->Rc = de->Rc;
194 if (de->Rc == ASSIGN_OK) {
195 ack->RcId = de->Id;
196 de->user[1] = de->Id;
197 } else {
198 ack->RcId = de->user[1];
199 }
200 ack->RcCh = de->RcCh;
201 ack->Reference = de->user[0];
202 skb_queue_tail(&ccard->rackq, skb);
203 eicon_schedule_ack(ccard);
204 eicon_log(ccard, 128, "idi_cbk: Ch%d: Rc=%x Id=%x RLen=%x compl=%x\n",
205 de->user[0], de->Rc, ack->RcId, de->RLength, de->complete);
206 }
207 } else {
208 /* Indication */
209 if (de->complete) {
210 len = de->RLength;
211 } else {
212 len = 270;
213 if (de->RLength <= 270)
214 eicon_log(ccard, 1, "eicon_cbk: ind not complete but <= 270\n");
215 }
216 skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
217 if (!skb) {
218 eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _idi_callback()\n");
219 } else {
220 ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
221 ind->Ind = de->Ind;
222 ind->IndId = de->user[1];
223 ind->IndCh = de->IndCh;
224 ind->MInd = de->Ind;
225 ind->RBuffer.length = len;
226 ind->MLength = de->RLength;
227 memcpy(&ind->RBuffer.P, &de->RBuffer->P, len);
228 skb_queue_tail(&ccard->rcvq, skb);
229 eicon_schedule_rx(ccard);
230 eicon_log(ccard, 128, "idi_cbk: Ch%d: Ind=%x Id=%x RLen=%x compl=%x\n",
231 de->user[0], de->Ind, ind->IndId, de->RLength, de->complete);
232 }
233 }
234
235 de->RNum = 0;
236 de->RNR = 0;
237 de->Rc = 0;
238 de->Ind = 0;
239 }
240 #endif /* CONFIG_ISDN_DRV_EICON_PCI */
241
242 /*
243 * Transmit-Function
244 */
245 void
246 eicon_io_transmit(eicon_card *ccard) {
247 eicon_isa_card *isa_card;
248 struct sk_buff *skb;
249 struct sk_buff *skb2;
250 unsigned long flags;
251 eicon_pr_ram *prram = 0;
252 eicon_isa_com *com = 0;
253 eicon_REQ *ReqOut = 0;
254 eicon_REQ *reqbuf = 0;
255 eicon_chan *chan;
256 eicon_chan_ptr *chan2;
257 int ReqCount;
258 int scom = 0;
259 int tmp = 0;
260 int tmpid = 0;
261 int quloop = 1;
262 int dlev = 0;
263 ENTITY *ep = 0;
264
265 isa_card = &ccard->hwif.isa;
266
267 if (!ccard) {
268 eicon_log(ccard, 1, "eicon_transmit: NULL card!\n");
269 return;
270 }
271
272 switch(ccard->type) {
273 #ifdef CONFIG_ISDN_DRV_EICON_ISA
274 case EICON_CTYPE_S:
275 case EICON_CTYPE_SX:
276 case EICON_CTYPE_SCOM:
277 case EICON_CTYPE_QUADRO:
278 scom = 1;
279 com = (eicon_isa_com *)isa_card->shmem;
280 break;
281 case EICON_CTYPE_S2M:
282 scom = 0;
283 prram = (eicon_pr_ram *)isa_card->shmem;
284 break;
285 #endif
286 #ifdef CONFIG_ISDN_DRV_EICON_PCI
287 case EICON_CTYPE_MAESTRAP:
288 scom = 2;
289 break;
290 case EICON_CTYPE_MAESTRAQ:
291 scom = 2;
292 break;
293 case EICON_CTYPE_MAESTRA:
294 scom = 2;
295 break;
296 #endif
297 default:
298 eicon_log(ccard, 1, "eicon_transmit: unsupported card-type!\n");
299 return;
300 }
301
302 ReqCount = 0;
303 if (!(skb2 = skb_dequeue(&ccard->sndq)))
304 quloop = 0;
305 while(quloop) {
306 spin_lock_irqsave(&eicon_lock, flags);
307 switch (scom) {
308 case 1:
309 if ((ram_inb(ccard, &com->Req)) || (ccard->ReadyInt)) {
310 if (!ccard->ReadyInt) {
311 tmp = ram_inb(ccard, &com->ReadyInt) + 1;
312 ram_outb(ccard, &com->ReadyInt, tmp);
313 ccard->ReadyInt++;
314 }
315 spin_unlock_irqrestore(&eicon_lock, flags);
316 skb_queue_head(&ccard->sndq, skb2);
317 eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");
318 return;
319 }
320 break;
321 case 0:
322 if (!(ram_inb(ccard, &prram->ReqOutput) - ram_inb(ccard, &prram->ReqInput))) {
323 spin_unlock_irqrestore(&eicon_lock, flags);
324 skb_queue_head(&ccard->sndq, skb2);
325 eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");
326 return;
327 }
328 break;
329 }
330 spin_unlock_irqrestore(&eicon_lock, flags);
331
332 chan2 = (eicon_chan_ptr *)skb2->data;
333 chan = chan2->ptr;
334 if (!chan->e.busy) {
335 if((skb = skb_dequeue(&chan->e.X))) {
336
337 reqbuf = (eicon_REQ *)skb->data;
338 if ((reqbuf->Reference) && (chan->e.B2Id == 0) && (reqbuf->ReqId & 0x1f)) {
339 eicon_log(ccard, 16, "eicon: transmit: error Id=0 on %d (Net)\n", chan->No);
340 } else {
341 spin_lock_irqsave(&eicon_lock, flags);
342
343 switch (scom) {
344 case 1:
345 ram_outw(ccard, &com->XBuffer.length, reqbuf->XBuffer.length);
346 ram_copytocard(ccard, &com->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
347 ram_outb(ccard, &com->ReqCh, reqbuf->ReqCh);
348 break;
349 case 0:
350 /* get address of next available request buffer */
351 ReqOut = (eicon_REQ *)&prram->B[ram_inw(ccard, &prram->NextReq)];
352 ram_outw(ccard, &ReqOut->XBuffer.length, reqbuf->XBuffer.length);
353 ram_copytocard(ccard, &ReqOut->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
354 ram_outb(ccard, &ReqOut->ReqCh, reqbuf->ReqCh);
355 ram_outb(ccard, &ReqOut->Req, reqbuf->Req);
356 break;
357 }
358
359 dlev = 160;
360
361 if (reqbuf->ReqId & 0x1f) { /* if this is no ASSIGN */
362
363 if (!reqbuf->Reference) { /* Signal Layer */
364 switch (scom) {
365 case 1:
366 ram_outb(ccard, &com->ReqId, chan->e.D3Id);
367 break;
368 case 0:
369 ram_outb(ccard, &ReqOut->ReqId, chan->e.D3Id);
370 break;
371 case 2:
372 ep = &chan->de;
373 break;
374 }
375 tmpid = chan->e.D3Id;
376 chan->e.ReqCh = 0;
377 }
378 else { /* Net Layer */
379 switch(scom) {
380 case 1:
381 ram_outb(ccard, &com->ReqId, chan->e.B2Id);
382 break;
383 case 0:
384 ram_outb(ccard, &ReqOut->ReqId, chan->e.B2Id);
385 break;
386 case 2:
387 ep = &chan->be;
388 break;
389 }
390 tmpid = chan->e.B2Id;
391 chan->e.ReqCh = 1;
392 if (((reqbuf->Req & 0x0f) == 0x08) ||
393 ((reqbuf->Req & 0x0f) == 0x01)) { /* Send Data */
394 chan->waitq = reqbuf->XBuffer.length;
395 chan->waitpq += reqbuf->XBuffer.length;
396 dlev = 128;
397 }
398 }
399
400 } else { /* It is an ASSIGN */
401
402 switch(scom) {
403 case 1:
404 ram_outb(ccard, &com->ReqId, reqbuf->ReqId);
405 break;
406 case 0:
407 ram_outb(ccard, &ReqOut->ReqId, reqbuf->ReqId);
408 break;
409 case 2:
410 if (!reqbuf->Reference)
411 ep = &chan->de;
412 else
413 ep = &chan->be;
414 ep->Id = reqbuf->ReqId;
415 break;
416 }
417 tmpid = reqbuf->ReqId;
418
419 if (!reqbuf->Reference)
420 chan->e.ReqCh = 0;
421 else
422 chan->e.ReqCh = 1;
423 }
424
425 switch(scom) {
426 case 1:
427 chan->e.ref = ccard->ref_out++;
428 break;
429 case 0:
430 chan->e.ref = ram_inw(ccard, &ReqOut->Reference);
431 break;
432 case 2:
433 chan->e.ref = chan->No;
434 break;
435 }
436
437 chan->e.Req = reqbuf->Req;
438 ReqCount++;
439
440 switch (scom) {
441 case 1:
442 ram_outb(ccard, &com->Req, reqbuf->Req);
443 break;
444 case 0:
445 ram_outw(ccard, &prram->NextReq, ram_inw(ccard, &ReqOut->next));
446 break;
447 case 2:
448 #ifdef CONFIG_ISDN_DRV_EICON_PCI
449 if (!ep) break;
450 ep->callback = eicon_idi_callback;
451 ep->R = (BUFFERS *)ccard;
452 ep->user[0] = (word)chan->No;
453 ep->user[1] = (word)tmpid;
454 ep->XNum = 1;
455 ep->RNum = 0;
456 ep->RNR = 0;
457 ep->Rc = 0;
458 ep->Ind = 0;
459 ep->X->PLength = reqbuf->XBuffer.length;
460 memcpy(ep->X->P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
461 ep->ReqCh = reqbuf->ReqCh;
462 ep->Req = reqbuf->Req;
463 #endif
464 break;
465 }
466
467 chan->e.busy = 1;
468 spin_unlock_irqrestore(&eicon_lock, flags);
469 eicon_log(ccard, dlev, "eicon: Req=%d Id=%x Ch=%d Len=%d Ref=%d\n",
470 reqbuf->Req, tmpid,
471 reqbuf->ReqCh, reqbuf->XBuffer.length,
472 chan->e.ref);
473 #ifdef CONFIG_ISDN_DRV_EICON_PCI
474 if (scom == 2) {
475 if (ep) {
476 ccard->d->request(ep);
477 if (ep->Rc)
478 eicon_idi_callback(ep);
479 }
480 }
481 #endif
482 }
483 dev_kfree_skb(skb);
484 }
485 dev_kfree_skb(skb2);
486 }
487 else {
488 skb_queue_tail(&ccard->sackq, skb2);
489 eicon_log(ccard, 128, "eicon: transmit: busy chan %d\n", chan->No);
490 }
491
492 switch(scom) {
493 case 1:
494 quloop = 0;
495 break;
496 case 0:
497 case 2:
498 if (!(skb2 = skb_dequeue(&ccard->sndq)))
499 quloop = 0;
500 break;
501 }
502
503 }
504 if (!scom)
505 ram_outb(ccard, &prram->ReqInput, (__u8)(ram_inb(ccard, &prram->ReqInput) + ReqCount));
506
507 while((skb = skb_dequeue(&ccard->sackq))) {
508 skb_queue_tail(&ccard->sndq, skb);
509 }
510 }
511
512 #ifdef CONFIG_ISDN_DRV_EICON_ISA
513 /*
514 * IRQ handler
515 */
516 void
517 eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
518 eicon_card *ccard = (eicon_card *)dev_id;
519 eicon_isa_card *isa_card;
520 eicon_pr_ram *prram = 0;
521 eicon_isa_com *com = 0;
522 eicon_RC *RcIn;
523 eicon_IND *IndIn;
524 struct sk_buff *skb;
525 int Count = 0;
526 int Rc = 0;
527 int Ind = 0;
528 unsigned char *irqprobe = 0;
529 int scom = 0;
530 int tmp = 0;
531 int dlev = 0;
532
533
534 if (!ccard) {
535 eicon_log(ccard, 1, "eicon_irq: spurious interrupt %d\n", irq);
536 return;
537 }
538
539 if (ccard->type == EICON_CTYPE_QUADRO) {
540 tmp = 4;
541 while(tmp) {
542 com = (eicon_isa_com *)ccard->hwif.isa.shmem;
543 if ((readb(ccard->hwif.isa.intack))) { /* quadro found */
544 break;
545 }
546 ccard = ccard->qnext;
547 tmp--;
548 }
549 }
550
551 isa_card = &ccard->hwif.isa;
552
553 switch(ccard->type) {
554 case EICON_CTYPE_S:
555 case EICON_CTYPE_SX:
556 case EICON_CTYPE_SCOM:
557 case EICON_CTYPE_QUADRO:
558 scom = 1;
559 com = (eicon_isa_com *)isa_card->shmem;
560 irqprobe = &isa_card->irqprobe;
561 break;
562 case EICON_CTYPE_S2M:
563 scom = 0;
564 prram = (eicon_pr_ram *)isa_card->shmem;
565 irqprobe = &isa_card->irqprobe;
566 break;
567 default:
568 eicon_log(ccard, 1, "eicon_irq: unsupported card-type!\n");
569 return;
570 }
571
572 if (*irqprobe) {
573 switch(ccard->type) {
574 case EICON_CTYPE_S:
575 case EICON_CTYPE_SX:
576 case EICON_CTYPE_SCOM:
577 case EICON_CTYPE_QUADRO:
578 if (readb(isa_card->intack)) {
579 writeb(0, &com->Rc);
580 writeb(0, isa_card->intack);
581 }
582 (*irqprobe)++;
583 break;
584 case EICON_CTYPE_S2M:
585 if (readb(isa_card->intack)) {
586 writeb(0, &prram->RcOutput);
587 writeb(0, isa_card->intack);
588 }
589 (*irqprobe)++;
590 break;
591 }
592 return;
593 }
594
595 switch(ccard->type) {
596 case EICON_CTYPE_S:
597 case EICON_CTYPE_SX:
598 case EICON_CTYPE_SCOM:
599 case EICON_CTYPE_QUADRO:
600 case EICON_CTYPE_S2M:
601 if (!(readb(isa_card->intack))) { /* card did not interrupt */
602 eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n");
603 return;
604 }
605 break;
606 }
607
608 if (scom) {
609
610 /* if a return code is available ... */
611 if ((tmp = ram_inb(ccard, &com->Rc))) {
612 eicon_RC *ack;
613 if (tmp == READY_INT) {
614 eicon_log(ccard, 64, "eicon: IRQ Rc=READY_INT\n");
615 if (ccard->ReadyInt) {
616 ccard->ReadyInt--;
617 ram_outb(ccard, &com->Rc, 0);
618 eicon_schedule_tx(ccard);
619 }
620 } else {
621 skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
622 if (!skb) {
623 eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n");
624 } else {
625 ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
626 ack->Rc = tmp;
627 ack->RcId = ram_inb(ccard, &com->RcId);
628 ack->RcCh = ram_inb(ccard, &com->RcCh);
629 ack->Reference = ccard->ref_in++;
630 eicon_log(ccard, 128, "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n",
631 tmp,ack->RcId,ack->RcCh,ack->Reference);
632 skb_queue_tail(&ccard->rackq, skb);
633 eicon_schedule_ack(ccard);
634 }
635 ram_outb(ccard, &com->Req, 0);
636 ram_outb(ccard, &com->Rc, 0);
637 }
638
639 } else {
640
641 /* if an indication is available ... */
642 if ((tmp = ram_inb(ccard, &com->Ind))) {
643 eicon_IND *ind;
644 int len = ram_inw(ccard, &com->RBuffer.length);
645 skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
646 if (!skb) {
647 eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n");
648 } else {
649 ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
650 ind->Ind = tmp;
651 ind->IndId = ram_inb(ccard, &com->IndId);
652 ind->IndCh = ram_inb(ccard, &com->IndCh);
653 ind->MInd = ram_inb(ccard, &com->MInd);
654 ind->MLength = ram_inw(ccard, &com->MLength);
655 ind->RBuffer.length = len;
656 if ((tmp == 1) || (tmp == 8))
657 dlev = 128;
658 else
659 dlev = 192;
660 eicon_log(ccard, dlev, "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
661 tmp,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len);
662 ram_copyfromcard(ccard, &ind->RBuffer.P, &com->RBuffer.P, len);
663 skb_queue_tail(&ccard->rcvq, skb);
664 eicon_schedule_rx(ccard);
665 }
666 ram_outb(ccard, &com->Ind, 0);
667 }
668 }
669
670 } else {
671
672 /* if return codes are available ... */
673 if((Count = ram_inb(ccard, &prram->RcOutput))) {
674 eicon_RC *ack;
675 /* get the buffer address of the first return code */
676 RcIn = (eicon_RC *)&prram->B[ram_inw(ccard, &prram->NextRc)];
677 /* for all return codes do ... */
678 while(Count--) {
679
680 if((Rc=ram_inb(ccard, &RcIn->Rc))) {
681 skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
682 if (!skb) {
683 eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n");
684 } else {
685 ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
686 ack->Rc = Rc;
687 ack->RcId = ram_inb(ccard, &RcIn->RcId);
688 ack->RcCh = ram_inb(ccard, &RcIn->RcCh);
689 ack->Reference = ram_inw(ccard, &RcIn->Reference);
690 eicon_log(ccard, 128, "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n",
691 Rc,ack->RcId,ack->RcCh,ack->Reference);
692 skb_queue_tail(&ccard->rackq, skb);
693 eicon_schedule_ack(ccard);
694 }
695 ram_outb(ccard, &RcIn->Rc, 0);
696 }
697 /* get buffer address of next return code */
698 RcIn = (eicon_RC *)&prram->B[ram_inw(ccard, &RcIn->next)];
699 }
700 /* clear all return codes (no chaining!) */
701 ram_outb(ccard, &prram->RcOutput, 0);
702 }
703
704 /* if indications are available ... */
705 if((Count = ram_inb(ccard, &prram->IndOutput))) {
706 eicon_IND *ind;
707 /* get the buffer address of the first indication */
708 IndIn = (eicon_IND *)&prram->B[ram_inw(ccard, &prram->NextInd)];
709 /* for all indications do ... */
710 while(Count--) {
711 Ind = ram_inb(ccard, &IndIn->Ind);
712 if(Ind) {
713 int len = ram_inw(ccard, &IndIn->RBuffer.length);
714 skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
715 if (!skb) {
716 eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n");
717 } else {
718 ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
719 ind->Ind = Ind;
720 ind->IndId = ram_inb(ccard, &IndIn->IndId);
721 ind->IndCh = ram_inb(ccard, &IndIn->IndCh);
722 ind->MInd = ram_inb(ccard, &IndIn->MInd);
723 ind->MLength = ram_inw(ccard, &IndIn->MLength);
724 ind->RBuffer.length = len;
725 if ((Ind == 1) || (Ind == 8))
726 dlev = 128;
727 else
728 dlev = 192;
729 eicon_log(ccard, dlev, "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
730 Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len);
731 ram_copyfromcard(ccard, &ind->RBuffer.P, &IndIn->RBuffer.P, len);
732 skb_queue_tail(&ccard->rcvq, skb);
733 eicon_schedule_rx(ccard);
734 }
735 ram_outb(ccard, &IndIn->Ind, 0);
736 }
737 /* get buffer address of next indication */
738 IndIn = (eicon_IND *)&prram->B[ram_inw(ccard, &IndIn->next)];
739 }
740 ram_outb(ccard, &prram->IndOutput, 0);
741 }
742
743 }
744
745 /* clear interrupt */
746 switch(ccard->type) {
747 case EICON_CTYPE_QUADRO:
748 writeb(0, isa_card->intack);
749 writeb(0, &com[0x401]);
750 break;
751 case EICON_CTYPE_S:
752 case EICON_CTYPE_SX:
753 case EICON_CTYPE_SCOM:
754 case EICON_CTYPE_S2M:
755 writeb(0, isa_card->intack);
756 break;
757 }
758
759 return;
760 }
761 #endif
762