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