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