Example #1
0
static void __exit
unregister_card(eicon_card * card)
{
        isdn_ctrl cmd;

        cmd.command = ISDN_STAT_UNLOAD;
        cmd.driver = card->myid;
        card->interface.statcallb(&cmd);
        switch (card->bus) {
#ifdef CONFIG_ISDN_DRV_EICON_ISA
		case EICON_BUS_ISA:
#ifdef CONFIG_MCA
		case EICON_BUS_MCA:
#endif /* CONFIG_MCA */
			eicon_isa_release(&card->hwif.isa);
			break;
#endif
		case EICON_BUS_PCI:
			break;
		default:
			eicon_log(card, 1,
			       "eicon: Invalid BUS type %d\n",
			       card->bus);
			break;
        }
}
Example #2
0
/*
 * register card at linklevel
 */
static int
eicon_registercard(eicon_card * card)
{
        switch (card->bus) {
#ifdef CONFIG_ISDN_DRV_EICON_ISA
		case EICON_BUS_ISA:
			/* TODO something to print */
			break;
#ifdef CONFIG_MCA
		case EICON_BUS_MCA:
			eicon_isa_printpar(&card->hwif.isa);
			break;
#endif /* CONFIG_MCA */
#endif
		case EICON_BUS_PCI:
			break;
		default:
			eicon_log(card, 1,
			       "eicon_registercard: Illegal BUS type %d\n",
			       card->bus);
			return -1;
        }
        if (!register_isdn(&card->interface)) {
                printk(KERN_WARNING
                       "eicon_registercard: Unable to register %s\n",
                       card->interface.id);
                return -1;
        }
        card->myid = card->interface.channels;
        sprintf(card->regname, "%s", card->interface.id);
        return 0;
}
Example #3
0
static eicon_chan *
find_channel(eicon_card *card, int channel)
{
	if ((channel >= 0) && (channel < card->nchannels))
        	return &(card->bch[channel]);
	eicon_log(card, 1, "eicon: Invalid channel %d\n", channel);
	return NULL;
}
Example #4
0
void
eicon_io_ack_dispatch(eicon_card *ccard) {
        struct sk_buff *skb;

        if (!ccard) {
		eicon_log(ccard, 1, "eicon_err: NULL card in ack_dispatch!\n");
                return;
        }
	while((skb = skb_dequeue(&ccard->rackq))) {
		idi_handle_ack(ccard, skb);
	}
}
Example #5
0
static void
eicon_transmit(struct eicon_card *card)
{
	switch (card->bus) {
		case EICON_BUS_ISA:
		case EICON_BUS_MCA:
		case EICON_BUS_PCI:
			eicon_io_transmit(card);
			break;
		default:
			eicon_log(card, 1,
			       "eicon_transmit: Illegal bustype %d\n", card->bus);
	}
}
Example #6
0
static void
eicon_rcv_dispatch(struct eicon_card *card)
{
	switch (card->bus) {
		case EICON_BUS_ISA:
		case EICON_BUS_MCA:
		case EICON_BUS_PCI:
			eicon_io_rcv_dispatch(card);
			break;
		default:
			eicon_log(card, 1,
			       "eicon_ack_dispatch: Illegal bustype %d\n", card->bus);
	}
}
Example #7
0
/*
 * IRQ handler 
 */
void
eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
	eicon_card *ccard = (eicon_card *)dev_id;
        eicon_isa_card *isa_card;
	eicon_pr_ram  *prram = 0;
	eicon_isa_com	*com = 0;
        eicon_RC *RcIn;
        eicon_IND *IndIn;
	struct sk_buff *skb;
        int Count = 0;
	int Rc = 0;
	int Ind = 0;
	unsigned char *irqprobe = 0;
	int scom = 0;
	int tmp = 0;
	int dlev = 0;


        if (!ccard) {
                eicon_log(ccard, 1, "eicon_irq: spurious interrupt %d\n", irq);
                return;
        }

	if (ccard->type == EICON_CTYPE_QUADRO) {
		tmp = 4;
		while(tmp) {
			com = (eicon_isa_com *)ccard->hwif.isa.shmem;
			if ((readb(ccard->hwif.isa.intack))) { /* quadro found */
				break;
			}
			ccard = ccard->qnext;
			tmp--;
		}
	}

	isa_card = &ccard->hwif.isa;

	switch(ccard->type) {
		case EICON_CTYPE_S:
		case EICON_CTYPE_SX:
		case EICON_CTYPE_SCOM:
		case EICON_CTYPE_QUADRO:
			scom = 1;
			com = (eicon_isa_com *)isa_card->shmem;
			irqprobe = &isa_card->irqprobe;
			break;
		case EICON_CTYPE_S2M:
			scom = 0;
			prram = (eicon_pr_ram *)isa_card->shmem;
			irqprobe = &isa_card->irqprobe;
			break;
		default:
                	eicon_log(ccard, 1, "eicon_irq: unsupported card-type!\n");
			return;
	}

	if (*irqprobe) {
		switch(ccard->type) {
			case EICON_CTYPE_S:
			case EICON_CTYPE_SX:
			case EICON_CTYPE_SCOM:
			case EICON_CTYPE_QUADRO:
				if (readb(isa_card->intack)) {
        		               	writeb(0, &com->Rc);
					writeb(0, isa_card->intack);
				}
				(*irqprobe)++;
				break;
			case EICON_CTYPE_S2M:
				if (readb(isa_card->intack)) {
        		               	writeb(0, &prram->RcOutput);
					writeb(0, isa_card->intack);
				}
				(*irqprobe)++;
				break;
		}
		return;
	}

	switch(ccard->type) {
		case EICON_CTYPE_S:
		case EICON_CTYPE_SX:
		case EICON_CTYPE_SCOM:
		case EICON_CTYPE_QUADRO:
		case EICON_CTYPE_S2M:
			if (!(readb(isa_card->intack))) { /* card did not interrupt */
				eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n");
				return;
			} 
			break;
	}

    if (scom) {

        /* if a return code is available ...  */
	if ((tmp = ram_inb(ccard, &com->Rc))) {
		eicon_RC *ack;
		if (tmp == READY_INT) {
                       	eicon_log(ccard, 64, "eicon: IRQ Rc=READY_INT\n");
			if (ccard->ReadyInt) {
				ccard->ReadyInt--;
				ram_outb(ccard, &com->Rc, 0);
				eicon_schedule_tx(ccard);
			}
		} else {
			skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
			if (!skb) {
                		eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n");
			} else {
				ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
				ack->Rc = tmp;
				ack->RcId = ram_inb(ccard, &com->RcId);
				ack->RcCh = ram_inb(ccard, &com->RcCh);
				ack->Reference = ccard->ref_in++;
               	        	eicon_log(ccard, 128, "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n",
					tmp,ack->RcId,ack->RcCh,ack->Reference);
				skb_queue_tail(&ccard->rackq, skb);
				eicon_schedule_ack(ccard);
			}
			ram_outb(ccard, &com->Req, 0);
			ram_outb(ccard, &com->Rc, 0);
		}

	} else {

	        /* if an indication is available ...  */
		if ((tmp = ram_inb(ccard, &com->Ind))) {
			eicon_IND *ind;
			int len = ram_inw(ccard, &com->RBuffer.length);
			skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
			if (!skb) {
                		eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n");
			} else {
				ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
				ind->Ind = tmp;
				ind->IndId = ram_inb(ccard, &com->IndId);
				ind->IndCh = ram_inb(ccard, &com->IndCh);
				ind->MInd  = ram_inb(ccard, &com->MInd);
				ind->MLength = ram_inw(ccard, &com->MLength);
				ind->RBuffer.length = len;
				if ((tmp == 1) || (tmp == 8))
					dlev = 128;
				else
					dlev = 192;
                       		eicon_log(ccard, dlev, "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
					tmp,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len);
				ram_copyfromcard(ccard, &ind->RBuffer.P, &com->RBuffer.P, len);
				skb_queue_tail(&ccard->rcvq, skb);
				eicon_schedule_rx(ccard);
			}
			ram_outb(ccard, &com->Ind, 0);
		}
	}

    } else {

        /* if return codes are available ...  */
        if((Count = ram_inb(ccard, &prram->RcOutput))) {
		eicon_RC *ack;
                /* get the buffer address of the first return code */
                RcIn = (eicon_RC *)&prram->B[ram_inw(ccard, &prram->NextRc)];
                /* for all return codes do ...  */
                while(Count--) {

                        if((Rc=ram_inb(ccard, &RcIn->Rc))) {
				skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
				if (!skb) {
                			eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n");
				} else {
					ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
					ack->Rc = Rc;
					ack->RcId = ram_inb(ccard, &RcIn->RcId);
					ack->RcCh = ram_inb(ccard, &RcIn->RcCh);
					ack->Reference = ram_inw(ccard, &RcIn->Reference);
        	                	eicon_log(ccard, 128, "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n",
						Rc,ack->RcId,ack->RcCh,ack->Reference);
					skb_queue_tail(&ccard->rackq, skb);
					eicon_schedule_ack(ccard);
				}
                       		ram_outb(ccard, &RcIn->Rc, 0);
                        }
                        /* get buffer address of next return code   */
                        RcIn = (eicon_RC *)&prram->B[ram_inw(ccard, &RcIn->next)];
                }
                /* clear all return codes (no chaining!) */
                ram_outb(ccard, &prram->RcOutput, 0);
        }

        /* if indications are available ... */
        if((Count = ram_inb(ccard, &prram->IndOutput))) {
		eicon_IND *ind;
                /* get the buffer address of the first indication */
                IndIn = (eicon_IND *)&prram->B[ram_inw(ccard, &prram->NextInd)];
                /* for all indications do ... */
                while(Count--) {
			Ind = ram_inb(ccard, &IndIn->Ind);
			if(Ind) {
				int len = ram_inw(ccard, &IndIn->RBuffer.length);
				skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
				if (!skb) {
                			eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n");
				} else {
					ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
					ind->Ind = Ind;
					ind->IndId = ram_inb(ccard, &IndIn->IndId);
					ind->IndCh = ram_inb(ccard, &IndIn->IndCh);
					ind->MInd  = ram_inb(ccard, &IndIn->MInd);
					ind->MLength = ram_inw(ccard, &IndIn->MLength);
					ind->RBuffer.length = len;
					if ((Ind == 1) || (Ind == 8))
						dlev = 128;
					else
						dlev = 192;
                	        	eicon_log(ccard, dlev, "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
						Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len);
	                                ram_copyfromcard(ccard, &ind->RBuffer.P, &IndIn->RBuffer.P, len);
					skb_queue_tail(&ccard->rcvq, skb);
					eicon_schedule_rx(ccard);
				}
				ram_outb(ccard, &IndIn->Ind, 0);
                        }
                        /* get buffer address of next indication  */
                        IndIn = (eicon_IND *)&prram->B[ram_inw(ccard, &IndIn->next)];
                }
                ram_outb(ccard, &prram->IndOutput, 0);
        }

    } 

	/* clear interrupt */
	switch(ccard->type) {
		case EICON_CTYPE_QUADRO:
			writeb(0, isa_card->intack);
			writeb(0, &com[0x401]);
			break;
		case EICON_CTYPE_S:
		case EICON_CTYPE_SX:
		case EICON_CTYPE_SCOM:
		case EICON_CTYPE_S2M:
			writeb(0, isa_card->intack);
			break;
	}

  return;
}
Example #8
0
/*
 *  Transmit-Function
 */
void
eicon_io_transmit(eicon_card *ccard) {
        eicon_isa_card *isa_card;
        struct sk_buff *skb;
        struct sk_buff *skb2;
        unsigned long flags;
	eicon_pr_ram  *prram = 0;
	eicon_isa_com	*com = 0;
	eicon_REQ *ReqOut = 0;
	eicon_REQ *reqbuf = 0;
	eicon_chan *chan;
	eicon_chan_ptr *chan2;
	int ReqCount;
	int scom = 0;
	int tmp = 0;
	int tmpid = 0;
	int quloop = 1;
	int dlev = 0;
	ENTITY *ep = 0;

	isa_card = &ccard->hwif.isa;

        if (!ccard) {
               	eicon_log(ccard, 1, "eicon_transmit: NULL card!\n");
                return;
        }

	switch(ccard->type) {
#ifdef CONFIG_ISDN_DRV_EICON_ISA
		case EICON_CTYPE_S:
		case EICON_CTYPE_SX:
		case EICON_CTYPE_SCOM:
		case EICON_CTYPE_QUADRO:
			scom = 1;
			com = (eicon_isa_com *)isa_card->shmem;
			break;
		case EICON_CTYPE_S2M:
			scom = 0;
			prram = (eicon_pr_ram *)isa_card->shmem;
			break;
#endif
#ifdef CONFIG_ISDN_DRV_EICON_PCI
		case EICON_CTYPE_MAESTRAP:
			scom = 2;
			break;
		case EICON_CTYPE_MAESTRAQ:
			scom = 2;
			break;
		case EICON_CTYPE_MAESTRA:
			scom = 2;
			break;
#endif
		default:
                	eicon_log(ccard, 1, "eicon_transmit: unsupported card-type!\n");
			return;
	}

	ReqCount = 0;
	if (!(skb2 = skb_dequeue(&ccard->sndq)))
		quloop = 0; 
	while(quloop) { 
		spin_lock_irqsave(&eicon_lock, flags);
		switch (scom) {
		  case 1:
			if ((ram_inb(ccard, &com->Req)) || (ccard->ReadyInt)) {
				if (!ccard->ReadyInt) {
					tmp = ram_inb(ccard, &com->ReadyInt) + 1;
					ram_outb(ccard, &com->ReadyInt, tmp);
					ccard->ReadyInt++;
				}
				spin_unlock_irqrestore(&eicon_lock, flags);
                	        skb_queue_head(&ccard->sndq, skb2);
       	                	eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");
	                        return;
			}
			break;
		  case 0:
	                if (!(ram_inb(ccard, &prram->ReqOutput) - ram_inb(ccard, &prram->ReqInput))) {
				spin_unlock_irqrestore(&eicon_lock, flags);
                	        skb_queue_head(&ccard->sndq, skb2);
       	                	eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");
	                        return;
        	        }
			break;
		}
		spin_unlock_irqrestore(&eicon_lock, flags);

		chan2 = (eicon_chan_ptr *)skb2->data;
		chan = chan2->ptr;
		if (!chan->e.busy) {
		 if((skb = skb_dequeue(&chan->e.X))) { 

		  reqbuf = (eicon_REQ *)skb->data;
		  if ((reqbuf->Reference) && (chan->e.B2Id == 0) && (reqbuf->ReqId & 0x1f)) {
			eicon_log(ccard, 16, "eicon: transmit: error Id=0 on %d (Net)\n", chan->No); 
		  } else {
			spin_lock_irqsave(&eicon_lock, flags);

			switch (scom) {
			  case 1:
				ram_outw(ccard, &com->XBuffer.length, reqbuf->XBuffer.length);
				ram_copytocard(ccard, &com->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
				ram_outb(ccard, &com->ReqCh, reqbuf->ReqCh);
				break;	
			  case 0:
				/* get address of next available request buffer */
				ReqOut = (eicon_REQ *)&prram->B[ram_inw(ccard, &prram->NextReq)];
				ram_outw(ccard, &ReqOut->XBuffer.length, reqbuf->XBuffer.length);
				ram_copytocard(ccard, &ReqOut->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
				ram_outb(ccard, &ReqOut->ReqCh, reqbuf->ReqCh);
				ram_outb(ccard, &ReqOut->Req, reqbuf->Req); 
				break;
			}

			dlev = 160;

			if (reqbuf->ReqId & 0x1f) { /* if this is no ASSIGN */

				if (!reqbuf->Reference) { /* Signal Layer */
					switch (scom) {
					  case 1:
						ram_outb(ccard, &com->ReqId, chan->e.D3Id); 
						break;
					  case 0:
						ram_outb(ccard, &ReqOut->ReqId, chan->e.D3Id); 
						break;
					  case 2:
						ep = &chan->de;
						break;
					}
					tmpid = chan->e.D3Id;
					chan->e.ReqCh = 0; 
				}
				else {			/* Net Layer */
					switch(scom) {
					  case 1:
						ram_outb(ccard, &com->ReqId, chan->e.B2Id); 
						break;
					  case 0:
						ram_outb(ccard, &ReqOut->ReqId, chan->e.B2Id); 
						break;
					  case 2:
						ep = &chan->be;
						break;
					}
					tmpid = chan->e.B2Id;
					chan->e.ReqCh = 1;
					if (((reqbuf->Req & 0x0f) == 0x08) ||
					   ((reqbuf->Req & 0x0f) == 0x01)) { /* Send Data */
						chan->waitq = reqbuf->XBuffer.length;
						chan->waitpq += reqbuf->XBuffer.length;
						dlev = 128;
					}
				}

			} else {	/* It is an ASSIGN */

				switch(scom) {
				  case 1:
					ram_outb(ccard, &com->ReqId, reqbuf->ReqId); 
					break;
				  case 0:
					ram_outb(ccard, &ReqOut->ReqId, reqbuf->ReqId); 
					break;
				  case 2:
					if (!reqbuf->Reference) 
						ep = &chan->de;
					else
						ep = &chan->be;
					ep->Id = reqbuf->ReqId;
					break;
				}
				tmpid = reqbuf->ReqId;

				if (!reqbuf->Reference) 
					chan->e.ReqCh = 0; 
				 else
					chan->e.ReqCh = 1; 
			} 

			switch(scom) {
			  case 1:
			 	chan->e.ref = ccard->ref_out++;
				break;
			  case 0:
			 	chan->e.ref = ram_inw(ccard, &ReqOut->Reference);
				break;
			  case 2:
				chan->e.ref = chan->No;
				break;
			}

			chan->e.Req = reqbuf->Req;
			ReqCount++; 

			switch (scom) {
			  case 1:
				ram_outb(ccard, &com->Req, reqbuf->Req); 
				break;
			  case 0:
				ram_outw(ccard, &prram->NextReq, ram_inw(ccard, &ReqOut->next)); 
				break;
			  case 2:
#ifdef CONFIG_ISDN_DRV_EICON_PCI
				if (!ep) break;
				ep->callback = eicon_idi_callback;
				ep->R = (BUFFERS *)ccard;
				ep->user[0] = (word)chan->No;
				ep->user[1] = (word)tmpid;
				ep->XNum = 1;
				ep->RNum = 0;
				ep->RNR = 0;
				ep->Rc = 0;
				ep->Ind = 0;
				ep->X->PLength = reqbuf->XBuffer.length;
				memcpy(ep->X->P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
				ep->ReqCh = reqbuf->ReqCh;
				ep->Req = reqbuf->Req;
#endif
				break;
			}

			chan->e.busy = 1;
			spin_unlock_irqrestore(&eicon_lock, flags);
	               	eicon_log(ccard, dlev, "eicon: Req=%d Id=%x Ch=%d Len=%d Ref=%d\n", 
					reqbuf->Req, tmpid, 
					reqbuf->ReqCh, reqbuf->XBuffer.length,
					chan->e.ref); 
#ifdef CONFIG_ISDN_DRV_EICON_PCI
			if (scom == 2) {
				if (ep) {
					ccard->d->request(ep);
					if (ep->Rc)
						eicon_idi_callback(ep);
				}
			}
#endif
		  }
		  dev_kfree_skb(skb);
		 }
		 dev_kfree_skb(skb2);
		} 
		else {
			skb_queue_tail(&ccard->sackq, skb2);
        	       	eicon_log(ccard, 128, "eicon: transmit: busy chan %d\n", chan->No); 
		}

		switch(scom) {
			case 1:
				quloop = 0;
				break;
			case 0:
			case 2:
				if (!(skb2 = skb_dequeue(&ccard->sndq)))
					quloop = 0;
				break;
		}

	}
	if (!scom)
		ram_outb(ccard, &prram->ReqInput, (__u8)(ram_inb(ccard, &prram->ReqInput) + ReqCount)); 

	while((skb = skb_dequeue(&ccard->sackq))) { 
		skb_queue_tail(&ccard->sndq, skb);
	}
}
Example #9
0
void
eicon_io_rcv_dispatch(eicon_card *ccard) {
	ulong flags;
        struct sk_buff *skb, *skb2, *skb_new;
        eicon_IND *ind, *ind2, *ind_new;
        eicon_chan *chan;

        if (!ccard) {
	        eicon_log(ccard, 1, "eicon_err: NULL card in rcv_dispatch !\n");
                return;
        }

	while((skb = skb_dequeue(&ccard->rcvq))) {
        	ind = (eicon_IND *)skb->data;

		spin_lock_irqsave(&eicon_lock, flags);
        	if ((chan = ccard->IdTable[ind->IndId]) == NULL) {
			spin_unlock_irqrestore(&eicon_lock, flags);
			if (DebugVar & 1) {
				switch(ind->Ind) {
					case N_DISC_ACK: 
						/* doesn't matter if this happens */ 
						break;
					default: 
						eicon_log(ccard, 1, "idi: Indication for unknown channel Ind=%d Id=%x\n", ind->Ind, ind->IndId);
						eicon_log(ccard, 1, "idi_hdl: Ch??: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
							ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
				}
			}
	                dev_kfree_skb(skb);
	                continue;
	        }
		spin_unlock_irqrestore(&eicon_lock, flags);

		if (chan->e.complete) { /* check for rec-buffer chaining */
			if (ind->MLength == ind->RBuffer.length) {
				chan->e.complete = 1;
				idi_handle_ind(ccard, skb);
				continue;
			}
			else {
				chan->e.complete = 0;
				ind->Ind = ind->MInd;
				skb_queue_tail(&chan->e.R, skb);
				continue;
			}
		}
		else {
			if (!(skb2 = skb_dequeue(&chan->e.R))) {
				chan->e.complete = 1;
                		eicon_log(ccard, 1, "eicon: buffer incomplete, but 0 in queue\n");
	                	dev_kfree_skb(skb);
				continue;	
			}
	        	ind2 = (eicon_IND *)skb2->data;
			skb_new = alloc_skb(((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length),
					GFP_ATOMIC);
			if (!skb_new) {
                		eicon_log(ccard, 1, "eicon_io: skb_alloc failed in rcv_dispatch()\n");
	                	dev_kfree_skb(skb);
	                	dev_kfree_skb(skb2);
				continue;	
			}
			ind_new = (eicon_IND *)skb_put(skb_new,
					((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length));
			ind_new->Ind = ind2->Ind;
			ind_new->IndId = ind2->IndId;
			ind_new->IndCh = ind2->IndCh;
			ind_new->MInd = ind2->MInd;
			ind_new->MLength = ind2->MLength;
			ind_new->RBuffer.length = ind2->RBuffer.length + ind->RBuffer.length;
			memcpy(&ind_new->RBuffer.P, &ind2->RBuffer.P, ind2->RBuffer.length);
			memcpy((&ind_new->RBuffer.P)+ind2->RBuffer.length, &ind->RBuffer.P, ind->RBuffer.length);
                	dev_kfree_skb(skb);
                	dev_kfree_skb(skb2);
			if (ind->MLength == ind->RBuffer.length) {
				chan->e.complete = 2;
				idi_handle_ind(ccard, skb_new);
				continue;
			}
			else {
				chan->e.complete = 0;
				skb_queue_tail(&chan->e.R, skb_new);
				continue;
			}
		}
	}
}
Example #10
0
/*
 *  IDI-Callback function
 */
void
eicon_idi_callback(ENTITY *de)
{
	eicon_card *ccard = (eicon_card *)de->R;
	struct sk_buff *skb;
	eicon_RC *ack;
	eicon_IND *ind;
	int len = 0;

	if (de->complete == 255) {
		/* Return Code */
		skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
		if (!skb) {
			eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _idi_callback()\n");
		} else {
			ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
			ack->Rc = de->Rc;
			if (de->Rc == ASSIGN_OK) {
				ack->RcId = de->Id;
				de->user[1] = de->Id;
			} else {
				ack->RcId = de->user[1];
			}
			ack->RcCh = de->RcCh;
			ack->Reference = de->user[0];
			skb_queue_tail(&ccard->rackq, skb);
			eicon_schedule_ack(ccard);
			eicon_log(ccard, 128, "idi_cbk: Ch%d: Rc=%x Id=%x RLen=%x compl=%x\n",
				de->user[0], de->Rc, ack->RcId, de->RLength, de->complete);
		}
	} else {
		/* Indication */
		if (de->complete) {
			len = de->RLength;
		} else {
			len = 270;
			if (de->RLength <= 270)
				eicon_log(ccard, 1, "eicon_cbk: ind not complete but <= 270\n");
		}
		skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
		if (!skb) {
			eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _idi_callback()\n");
		} else {
			ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
			ind->Ind = de->Ind;
			ind->IndId = de->user[1];
			ind->IndCh = de->IndCh;
			ind->MInd  = de->Ind;
			ind->RBuffer.length = len;
			ind->MLength = de->RLength;
			memcpy(&ind->RBuffer.P, &de->RBuffer->P, len);
			skb_queue_tail(&ccard->rcvq, skb);
			eicon_schedule_rx(ccard);
			eicon_log(ccard, 128, "idi_cbk: Ch%d: Ind=%x Id=%x RLen=%x compl=%x\n",
				de->user[0], de->Ind, ind->IndId, de->RLength, de->complete);
		}
	}

	de->RNum = 0;
	de->RNR = 0;
	de->Rc = 0;
	de->Ind = 0;
}
Example #11
0
/*
 * Allocate a new card-struct, initialize it
 * link it into cards-list.
 */
static void
eicon_alloccard(int Type, int membase, int irq, char *id, int card_id)
{
	int i;
	int j;
	int qloop;
#ifdef CONFIG_ISDN_DRV_EICON_ISA
	char qid[5];
#endif
        eicon_card *card;

	qloop = (Type == EICON_CTYPE_QUADRO)?2:0;
	for (i = 0; i <= qloop; i++) {
		if (!(card = (eicon_card *) kmalloc(sizeof(eicon_card), GFP_KERNEL))) {
			eicon_log(card, 1,
			       "eicon: (%s) Could not allocate card-struct.\n", id);
			return;
		}
		memset((char *) card, 0, sizeof(eicon_card));
		skb_queue_head_init(&card->sndq);
		skb_queue_head_init(&card->rcvq);
		skb_queue_head_init(&card->rackq);
		skb_queue_head_init(&card->sackq);
		skb_queue_head_init(&card->statq);
		card->statq_entries = 0;
		card->snd_tq.routine = (void *) (void *) eicon_transmit;
		card->snd_tq.data = card;
		card->rcv_tq.routine = (void *) (void *) eicon_rcv_dispatch;
		card->rcv_tq.data = card;
		card->ack_tq.routine = (void *) (void *) eicon_ack_dispatch;
		card->ack_tq.data = card;
		card->interface.maxbufsize = 4000;
		card->interface.command = if_command;
		card->interface.writebuf_skb = if_sendbuf;
		card->interface.writecmd = if_writecmd;
		card->interface.readstat = if_readstatus;
		card->interface.features =
			ISDN_FEATURE_L2_X75I |
			ISDN_FEATURE_L2_HDLC |
			ISDN_FEATURE_L2_TRANS |
			ISDN_FEATURE_L3_TRANS |
			ISDN_FEATURE_P_UNKNOWN;
		card->interface.hl_hdrlen = 20;
		card->ptype = ISDN_PTYPE_UNKNOWN;
		strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);
		card->myid = -1;
		card->type = Type;
		switch (Type) {
#ifdef CONFIG_ISDN_DRV_EICON_ISA
#if CONFIG_MCA /* only needed for MCA */
                        case EICON_CTYPE_S:
                        case EICON_CTYPE_SX:
                        case EICON_CTYPE_SCOM:
				if (MCA_bus) {
	                                if (membase == -1)
        	                                membase = EICON_ISA_MEMBASE;
                	                if (irq == -1)
                        	                irq = EICON_ISA_IRQ;
	                                card->bus = EICON_BUS_MCA;
        	                        card->hwif.isa.card = (void *)card;
                	                card->hwif.isa.shmem = (eicon_isa_shmem *)membase;
					card->hwif.isa.physmem = (unsigned long)membase;
                        	        card->hwif.isa.master = 1;

	                                card->hwif.isa.irq = irq;
        	                        card->hwif.isa.type = Type;
                	                card->nchannels = 2;
                        	        card->interface.channels = 1;
				} else {
					printk(KERN_WARNING
						"eicon (%s): no MCA bus detected.\n",
						card->interface.id);
					kfree(card);
					return;
				}
                                break;
#endif /* CONFIG_MCA */
			case EICON_CTYPE_QUADRO:
				if (membase == -1)
					membase = EICON_ISA_MEMBASE;
				if (irq == -1)
					irq = EICON_ISA_IRQ;
                                card->bus = EICON_BUS_ISA;
				card->hwif.isa.card = (void *)card;
				card->hwif.isa.shmem = (eicon_isa_shmem *)(membase + (i+1) * EICON_ISA_QOFFSET);
				card->hwif.isa.physmem = (unsigned long)(membase + (i+1) * EICON_ISA_QOFFSET);
				card->hwif.isa.master = 0;
				strcpy(card->interface.id, id);
				if (id[strlen(id) - 1] == 'a') {
					card->interface.id[strlen(id) - 1] = 'a' + i + 1;
				} else {
					sprintf(qid, "_%c",'2' + i);
					strcat(card->interface.id, qid);
				}
				printk(KERN_INFO "Eicon: Quadro: Driver-Id %s added.\n",
					card->interface.id);
				if (i == 0) {
					eicon_card *p = cards;
					while(p) {
						if ((p->hwif.isa.master) && (p->hwif.isa.irq == irq)) {
							p->qnext = card;
							break;
						}
						p = p->next;
					}
					if (!p) {
						eicon_log(card, 1, "eicon_alloccard: Quadro Master not found.\n");
						kfree(card);
						return;
					}
				} else {
					cards->qnext = card;
				}
				card->hwif.isa.irq = irq;
				card->hwif.isa.type = Type;
				card->nchannels = 2;
				card->interface.channels = 1;
				break;
#endif
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
			case EICON_CTYPE_MAESTRA:
                                card->bus = EICON_BUS_PCI;
				card->interface.features |=
					ISDN_FEATURE_L2_V11096 |
					ISDN_FEATURE_L2_V11019 |
					ISDN_FEATURE_L2_V11038 |
					ISDN_FEATURE_L2_MODEM |
					ISDN_FEATURE_L2_FAX | 
					ISDN_FEATURE_L3_TRANSDSP |
					ISDN_FEATURE_L3_FCLASS2;
                                card->hwif.pci.card = (void *)card;
                                card->hwif.pci.master = card_id;
                                card->hwif.pci.irq = irq;
                                card->hwif.pci.type = Type;
				card->flags = 0;
                                card->nchannels = 2;
				card->interface.channels = 1;
				break;

			case EICON_CTYPE_MAESTRAQ:
                                card->bus = EICON_BUS_PCI;
				card->interface.features |=
					ISDN_FEATURE_L2_V11096 |
					ISDN_FEATURE_L2_V11019 |
					ISDN_FEATURE_L2_V11038 |
					ISDN_FEATURE_L2_MODEM |
					ISDN_FEATURE_L2_FAX | 
					ISDN_FEATURE_L3_TRANSDSP |
					ISDN_FEATURE_L3_FCLASS2;
                                card->hwif.pci.card = (void *)card;
                                card->hwif.pci.master = card_id;
                                card->hwif.pci.irq = irq;
                                card->hwif.pci.type = Type;
				card->flags = 0;
                                card->nchannels = 2;
				card->interface.channels = 1;
				break;

			case EICON_CTYPE_MAESTRAP:
                                card->bus = EICON_BUS_PCI;
				card->interface.features |=
					ISDN_FEATURE_L2_V11096 |
					ISDN_FEATURE_L2_V11019 |
					ISDN_FEATURE_L2_V11038 |
					ISDN_FEATURE_L2_MODEM |
					ISDN_FEATURE_L2_FAX |
					ISDN_FEATURE_L3_TRANSDSP |
					ISDN_FEATURE_L3_FCLASS2;
                                card->hwif.pci.card = (void *)card;
                                card->hwif.pci.master = card_id;
                                card->hwif.pci.irq = irq;
                                card->hwif.pci.type = Type;
				card->flags = 0;
                                card->nchannels = 30;
				card->interface.channels = 1;
				break;
#endif
#endif
#ifdef CONFIG_ISDN_DRV_EICON_ISA
			case EICON_CTYPE_ISABRI:
				if (membase == -1)
					membase = EICON_ISA_MEMBASE;
				if (irq == -1)
					irq = EICON_ISA_IRQ;
				card->bus = EICON_BUS_ISA;
				card->hwif.isa.card = (void *)card;
				card->hwif.isa.shmem = (eicon_isa_shmem *)membase;
				card->hwif.isa.physmem = (unsigned long)membase;
				card->hwif.isa.master = 1;
				card->hwif.isa.irq = irq;
				card->hwif.isa.type = Type;
				card->nchannels = 2;
				card->interface.channels = 1;
				break;
			case EICON_CTYPE_ISAPRI:
				if (membase == -1)
					membase = EICON_ISA_MEMBASE;
				if (irq == -1)
					irq = EICON_ISA_IRQ;
                                card->bus = EICON_BUS_ISA;
				card->hwif.isa.card = (void *)card;
				card->hwif.isa.shmem = (eicon_isa_shmem *)membase;
				card->hwif.isa.physmem = (unsigned long)membase;
				card->hwif.isa.master = 1;
				card->hwif.isa.irq = irq;
				card->hwif.isa.type = Type;
				card->nchannels = 30;
				card->interface.channels = 1;
				break;
#endif
			default:
				eicon_log(card, 1, "eicon_alloccard: Invalid type %d\n", Type);
				kfree(card);
				return;
		}
		if (!(card->bch = (eicon_chan *) kmalloc(sizeof(eicon_chan) * (card->nchannels + 1)
							 , GFP_KERNEL))) {
			eicon_log(card, 1,
			       "eicon: (%s) Could not allocate bch-struct.\n", id);
			kfree(card);
			return;
		}
		for (j=0; j< (card->nchannels + 1); j++) {
			memset((char *)&card->bch[j], 0, sizeof(eicon_chan));
			card->bch[j].statectrl = 0;
			card->bch[j].l2prot = ISDN_PROTO_L2_X75I;
			card->bch[j].l3prot = ISDN_PROTO_L3_TRANS;
			card->bch[j].e.D3Id = 0;
			card->bch[j].e.B2Id = 0;
			card->bch[j].e.Req = 0;
			card->bch[j].No = j;
			card->bch[j].tskb1 = NULL;
			card->bch[j].tskb2 = NULL;
			skb_queue_head_init(&card->bch[j].e.X);
			skb_queue_head_init(&card->bch[j].e.R);
		}

#ifdef CONFIG_ISDN_DRV_EICON_PCI
		/* *** Diva Server *** */
		if (!(card->dbuf = (DBUFFER *) kmalloc((sizeof(DBUFFER) * (card->nchannels + 1))*2
							 , GFP_KERNEL))) {
			eicon_log(card, 1,
			       "eicon: (%s) Could not allocate DBUFFER-struct.\n", id);
			kfree(card);
			kfree(card->bch);
			return;
		}
		if (!(card->sbuf = (BUFFERS *) kmalloc((sizeof(BUFFERS) * (card->nchannels + 1)) * 2, GFP_KERNEL))) {
			eicon_log(card, 1,
			       "eicon: (%s) Could not allocate BUFFERS-struct.\n", id);
			kfree(card);
			kfree(card->bch);
			kfree(card->dbuf);
			return;
		}
		if (!(card->sbufp = (char *) kmalloc((270 * (card->nchannels + 1)) * 2, GFP_KERNEL))) {
			eicon_log(card, 1,
			       "eicon: (%s) Could not allocate BUFFERSP-struct.\n", id);
			kfree(card);
			kfree(card->bch);
			kfree(card->dbuf);
			kfree(card->sbuf);
			return;
		}
		for (j=0; j< (card->nchannels + 1); j++) {
			memset((char *)&card->dbuf[j], 0, sizeof(DBUFFER));
			card->bch[j].de.RBuffer = (DBUFFER *)&card->dbuf[j];
			memset((char *)&card->dbuf[j+(card->nchannels+1)], 0, sizeof(BUFFERS));
			card->bch[j].be.RBuffer = (DBUFFER *)&card->dbuf[j+(card->nchannels+1)];

			memset((char *)&card->sbuf[j], 0, sizeof(BUFFERS));
			card->bch[j].de.X = (BUFFERS *)&card->sbuf[j];
			memset((char *)&card->sbuf[j+(card->nchannels+1)], 0, sizeof(BUFFERS));
			card->bch[j].be.X = (BUFFERS *)&card->sbuf[j+(card->nchannels+1)];

			memset((char *)&card->sbufp[j], 0, 270);
			card->bch[j].de.X->P = (char *)&card->sbufp[j * 270];
			memset((char *)&card->sbufp[j+(card->nchannels+1)], 0, 270);
			card->bch[j].be.X->P = (char *)&card->sbufp[(j+(card->nchannels+1)) * 270];
		}
		/* *** */
#endif /* CONFIG_ISDN_DRV_EICON_PCI */

		card->next = cards;
		cards = card;
	}
}
Example #12
0
static int
eicon_command(eicon_card * card, isdn_ctrl * c)
{
        ulong a;
        eicon_chan *chan;
	eicon_cdef cdef;
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
	dia_start_t dstart;
        int idi_length = 0;
#endif
#endif
	isdn_ctrl cmd;
	int ret = 0;
	unsigned long flags;
 
	eicon_log(card, 16, "eicon_cmd 0x%x with arg 0x%lx (0x%lx)\n",
		c->command, c->arg, (ulong) *c->parm.num);

        switch (c->command) {
		case ISDN_CMD_IOCTL:
			memcpy(&a, c->parm.num, sizeof(ulong));
			switch (c->arg) {
				case EICON_IOCTL_GETVER:
					return(EICON_CTRL_VERSION);
				case EICON_IOCTL_GETTYPE:
					if (card->bus == EICON_BUS_PCI) {
						copy_to_user((char *)a, &card->hwif.pci.master, sizeof(int));
					}
					return(card->type);
				case EICON_IOCTL_GETMMIO:
					switch (card->bus) {
						case EICON_BUS_ISA:
						case EICON_BUS_MCA:
							return (int)card->hwif.isa.shmem;
						default:
							eicon_log(card, 1,
							       "eicon: Illegal BUS type %d\n",
							       card->bus);
							ret = -ENODEV;
					}
#ifdef CONFIG_ISDN_DRV_EICON_ISA
				case EICON_IOCTL_SETMMIO:
					if (card->flags & EICON_FLAGS_LOADED)
						return -EBUSY;
					switch (card->bus) {
						case EICON_BUS_ISA:
							if (eicon_isa_find_card(a,
								card->hwif.isa.irq,
								card->regname) < 0)
								return -EFAULT;
							card->hwif.isa.shmem = (eicon_isa_shmem *)a;
							return 0;
						case EICON_BUS_MCA:
#if CONFIG_MCA
							if (eicon_mca_find_card(
								0, a,
								card->hwif.isa.irq,
								card->regname) < 0)
								return -EFAULT;
							card->hwif.isa.shmem = (eicon_isa_shmem *)a;
							return 0;
#endif /* CONFIG_MCA */
						default:
							eicon_log(card, 1,
						      		"eicon: Illegal BUS type %d\n",
							       card->bus);
							ret = -ENODEV;
					}					
#endif
				case EICON_IOCTL_GETIRQ:
					switch (card->bus) {
						case EICON_BUS_ISA:
						case EICON_BUS_MCA:
							return card->hwif.isa.irq;
						default:
							eicon_log(card, 1,
							       "eicon: Illegal BUS type %d\n",
							       card->bus);
							ret = -ENODEV;
					}
				case EICON_IOCTL_SETIRQ:
					if (card->flags & EICON_FLAGS_LOADED)
						return -EBUSY;
					if ((a < 2) || (a > 15))
						return -EFAULT;
					switch (card->bus) {
						case EICON_BUS_ISA:
						case EICON_BUS_MCA:
							card->hwif.isa.irq = a;
							return 0;
						default:
							eicon_log(card, 1,
						      		"eicon: Illegal BUS type %d\n",
							       card->bus);
							ret = -ENODEV;
					}					
#ifdef CONFIG_ISDN_DRV_EICON_ISA
				case EICON_IOCTL_LOADBOOT:
					if (card->flags & EICON_FLAGS_RUNNING)
						return -EBUSY;  
					switch (card->bus) {
						case EICON_BUS_ISA:
						case EICON_BUS_MCA:
							ret = eicon_isa_bootload(
								&(card->hwif.isa),
								&(((eicon_codebuf *)a)->isa));
							break;
						default:
							eicon_log(card, 1,
							       "eicon: Illegal BUS type %d\n",
							       card->bus);
							ret = -ENODEV;
					}
					return ret;
#endif
#ifdef CONFIG_ISDN_DRV_EICON_ISA
				case EICON_IOCTL_LOADISA:
					if (card->flags & EICON_FLAGS_RUNNING)
						return -EBUSY;  
					switch (card->bus) {
						case EICON_BUS_ISA:
						case EICON_BUS_MCA:
							ret = eicon_isa_load(
								&(card->hwif.isa),
								&(((eicon_codebuf *)a)->isa));
							if (!ret) {
                                                                card->flags |= EICON_FLAGS_LOADED;
                                                                card->flags |= EICON_FLAGS_RUNNING;
								if (card->hwif.isa.channels > 1) {
									cmd.command = ISDN_STAT_ADDCH;
									cmd.driver = card->myid;
									cmd.arg = card->hwif.isa.channels - 1;
									card->interface.statcallb(&cmd);
								}
								cmd.command = ISDN_STAT_RUN;    
								cmd.driver = card->myid;        
								cmd.arg = 0;                    
								card->interface.statcallb(&cmd);
							}
							break;
						default:
							eicon_log(card, 1,
							       "eicon: Illegal BUS type %d\n",
							       card->bus);
							ret = -ENODEV;
					}
					return ret;
#endif
				case EICON_IOCTL_MANIF:
					if (!card->flags & EICON_FLAGS_RUNNING)
						return -ENODEV;
					if (!card->d)
						return -ENODEV;
					if (!card->d->features & DI_MANAGE)
						return -ENODEV;
					ret = eicon_idi_manage(
						card, 
						(eicon_manifbuf *)a);
					return ret;

				case EICON_IOCTL_GETXLOG:
					return -ENODEV;

				case EICON_IOCTL_ADDCARD:
					if ((ret = copy_from_user(&cdef, (char *)a, sizeof(cdef))))
						return -EFAULT;
					if (!(eicon_addcard(0, cdef.membase, cdef.irq, cdef.id, 0)))
						return -EIO;
					return 0;
				case EICON_IOCTL_DEBUGVAR:
					DebugVar = a;
					eicon_log(card, 1, "Eicon: Debug Value set to %ld\n", DebugVar);
					return 0;
#ifdef MODULE
				case EICON_IOCTL_FREEIT:
					while (MOD_USE_COUNT > 0) MOD_DEC_USE_COUNT;
					MOD_INC_USE_COUNT;
					return 0;
#endif
				case EICON_IOCTL_LOADPCI:
					eicon_log(card, 1, "Eicon: Wrong version of load-utility,\n");
					eicon_log(card, 1, "Eicon: re-compile eiconctrl !\n");
					eicon_log(card, 1, "Eicon: Maybe update of utility is necessary !\n");
					return -EINVAL;
				default:	
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
					if (c->arg < EICON_IOCTL_DIA_OFFSET)
						return -EINVAL;
					if (copy_from_user(&dstart, (char *)a, sizeof(dstart)))
						return -1;
					if (!(card = eicon_findnpcicard(dstart.card_id)))
						return -EINVAL;
					ret = do_ioctl(NULL, NULL,
						c->arg - EICON_IOCTL_DIA_OFFSET,
						(unsigned long) a);
					if (((c->arg - EICON_IOCTL_DIA_OFFSET)==DIA_IOCTL_START) && (!ret)) {
						if (card->type != EICON_CTYPE_MAESTRAQ) {
							DIVA_DIDD_Read(idi_d, sizeof(idi_d));
                                                        for(idi_length = 0; idi_length < 32; idi_length++) {
                                                          if (idi_d[idi_length].type == 0) break;
                                                        }
                                                        if ((idi_length < 1) || (idi_length >= 32)) {
					                  eicon_log(card, 1, "eicon: invalid idi table length.\n");
                                                          break;
                                                        }
							card->d = &idi_d[idi_length - 1];
							card->flags |= EICON_FLAGS_LOADED;
							card->flags |= EICON_FLAGS_RUNNING;
							eicon_pci_init_conf(card);
							if (card->d->channels > 1) {
								cmd.command = ISDN_STAT_ADDCH;
								cmd.driver = card->myid;
								cmd.arg = card->d->channels - 1;
								card->interface.statcallb(&cmd);
							}
							cmd.command = ISDN_STAT_RUN;    
							cmd.driver = card->myid;        
							cmd.arg = 0;                    
							card->interface.statcallb(&cmd);
							eicon_log(card, 1, "Eicon: %s started, %d channels (feat. 0x%x)\n",
								(card->type == EICON_CTYPE_MAESTRA) ? "BRI" : "PRI",
								card->d->channels, card->d->features);
						} else {
							int i;
							DIVA_DIDD_Read(idi_d, sizeof(idi_d));
                                                        for(idi_length = 0; idi_length < 32; idi_length++)
                                                          if (idi_d[idi_length].type == 0) break;
                                                        if ((idi_length < 1) || (idi_length >= 32)) {
					                  eicon_log(card, 1, "eicon: invalid idi table length.\n");
                                                          break;
                                                        }
        						for(i = 3; i >= 0; i--) {
								if (!(card = eicon_findnpcicard(dstart.card_id - i)))
									return -EINVAL;
	
								card->flags |= EICON_FLAGS_LOADED;
								card->flags |= EICON_FLAGS_RUNNING;
								card->d = &idi_d[idi_length - (i+1)];
								eicon_pci_init_conf(card);
								if (card->d->channels > 1) {
									cmd.command = ISDN_STAT_ADDCH;
									cmd.driver = card->myid;
									cmd.arg = card->d->channels - 1;
									card->interface.statcallb(&cmd);
								}
								cmd.command = ISDN_STAT_RUN;    
								cmd.driver = card->myid;        
								cmd.arg = 0;                    
								card->interface.statcallb(&cmd);
								eicon_log(card, 1, "Eicon: %d/4BRI started, %d channels (feat. 0x%x)\n",
									4-i, card->d->channels, card->d->features);
							}
						}
					}
					return ret;
#else
					return -EINVAL;
#endif
#endif /* CONFIG_PCI */
			}
			break;
		case ISDN_CMD_DIAL:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			spin_lock_irqsave(&eicon_lock, flags);
			if ((chan->fsm_state != EICON_STATE_NULL) && (chan->fsm_state != EICON_STATE_LISTEN)) {
				spin_unlock_irqrestore(&eicon_lock, flags);
				eicon_log(card, 1, "Dial on channel %d with state %d\n",
					chan->No, chan->fsm_state);
				return -EBUSY;
			}
			chan->fsm_state = EICON_STATE_OCALL;
			spin_unlock_irqrestore(&eicon_lock, flags);
			
			ret = idi_connect_req(card, chan, c->parm.setup.phone,
						     c->parm.setup.eazmsn,
						     c->parm.setup.si1,
						     c->parm.setup.si2);
			if (ret) {
				cmd.driver = card->myid;
				cmd.command = ISDN_STAT_DHUP;
				cmd.arg &= 0x1f;
				card->interface.statcallb(&cmd);
			}
			return ret;
		case ISDN_CMD_ACCEPTD:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			if (chan->fsm_state == EICON_STATE_ICALL) { 
				idi_connect_res(card, chan);
			}
			return 0;
		case ISDN_CMD_ACCEPTB:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			return 0;
		case ISDN_CMD_HANGUP:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			idi_hangup(card, chan);
			return 0;
		case ISDN_CMD_SETEAZ:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			chan->eazmask = 0x3ff;
			eicon_idi_listen_req(card, chan);
			return 0;
		case ISDN_CMD_CLREAZ:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			chan->eazmask = 0;
			eicon_idi_listen_req(card, chan);
			return 0;
		case ISDN_CMD_SETL2:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			chan->l2prot = (c->arg >> 8);
			return 0;
		case ISDN_CMD_GETL2:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			return chan->l2prot;
		case ISDN_CMD_SETL3:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			chan->l3prot = (c->arg >> 8);
#ifdef CONFIG_ISDN_TTY_FAX
			if (chan->l3prot == ISDN_PROTO_L3_FCLASS2) {
				chan->fax = c->parm.fax;
				eicon_log(card, 128, "idi_cmd: Ch%d: SETL3 struct fax=0x%x\n",chan->No, chan->fax);
			}
#endif
			return 0;
		case ISDN_CMD_GETL3:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			return chan->l3prot;
		case ISDN_CMD_GETEAZ:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			eicon_log(card, 1, "eicon CMD_GETEAZ not implemented\n");
			return 0;
		case ISDN_CMD_SETSIL:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			eicon_log(card, 1, "eicon CMD_SETSIL not implemented\n");
			return 0;
		case ISDN_CMD_GETSIL:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			eicon_log(card, 1, "eicon CMD_GETSIL not implemented\n");
			return 0;
		case ISDN_CMD_LOCK:
			MOD_INC_USE_COUNT;
			return 0;
		case ISDN_CMD_UNLOCK:
			MOD_DEC_USE_COUNT;
			return 0;
#ifdef CONFIG_ISDN_TTY_FAX
		case ISDN_CMD_FAXCMD:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			if (!chan->fax)
				break;
			idi_fax_cmd(card, chan);
			return 0;
#endif
		case ISDN_CMD_AUDIO:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			idi_audio_cmd(card, chan, c->arg >> 8, c->parm.num);
			return 0;
		case CAPI_PUT_MESSAGE:
			if (!card->flags & EICON_FLAGS_RUNNING)
				return -ENODEV;
			if (!(chan = find_channel(card, c->arg & 0x1f)))
				break;
			if (c->parm.cmsg.Length < 8)
				break;
			switch(c->parm.cmsg.Command) {
				case CAPI_FACILITY:
					if (c->parm.cmsg.Subcommand == CAPI_REQ)
						return(capipmsg(card, chan, &c->parm.cmsg));
					break;
				case CAPI_MANUFACTURER:
				default:
					break;
			}
			return 0;
        }
	
        return -EINVAL;
}
Example #13
0
static int __init
eicon_init(void)
{
	int card_count = 0;
	char tmprev[50];

	DebugVar = 1;
	eicon_lock = (spinlock_t) SPIN_LOCK_UNLOCKED;

        printk(KERN_INFO "%s Rev: ", DRIVERNAME);
	strcpy(tmprev, eicon_revision);
	printk("%s/", eicon_getrev(tmprev));
	strcpy(tmprev, eicon_pci_revision);
#ifdef CONFIG_ISDN_DRV_EICON_PCI
	printk("%s/", eicon_getrev(tmprev));
#else
	printk("---/");
#endif
	strcpy(tmprev, eicon_isa_revision);
#ifdef CONFIG_ISDN_DRV_EICON_ISA
	printk("%s/", eicon_getrev(tmprev));
#else
	printk("---/");
#endif
	strcpy(tmprev, eicon_idi_revision);
	printk("%s\n", eicon_getrev(tmprev));
        printk(KERN_INFO "%s Release: %s%s\n", DRIVERNAME,
		DRIVERRELEASE, DRIVERPATCH);

#ifdef CONFIG_ISDN_DRV_EICON_ISA
#ifdef CONFIG_MCA
	/* Check if we have MCA-bus */
        if (!MCA_bus)
                {
                printk(KERN_INFO
                        "eicon: No MCA bus, ISDN-interfaces  not probed.\n");
        } else {
		eicon_log(NULL, 8,
			"eicon_mca_find_card, irq=%d.\n", 
				irq);
               	if (!eicon_mca_find_card(0, membase, irq, id))
                       card_count++;
        };
#else
	card_count = eicon_addcard(0, membase, irq, id, 0);
#endif /* CONFIG_MCA */
#endif /* CONFIG_ISDN_DRV_EICON_ISA */
 
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
	DivasCardsDiscover();
	card_count += eicon_pci_find_card(id);
#endif
#endif

        if (!cards) {
#ifdef MODULE
#ifndef CONFIG_ISDN_DRV_EICON_PCI
#ifndef CONFIG_ISDN_DRV_EICON_ISA
                printk(KERN_INFO "Eicon: Driver is neither ISA nor PCI compiled !\n");
                printk(KERN_INFO "Eicon: Driver not loaded !\n");
#else
                printk(KERN_INFO "Eicon: No cards defined, driver not loaded !\n");
#endif
#else
                printk(KERN_INFO "Eicon: No PCI-cards found, driver not loaded !\n");
#endif
#endif /* MODULE */
		return -ENODEV;

	} else
		printk(KERN_INFO "Eicon: %d card%s added\n", card_count, 
                       (card_count>1)?"s":"");
        return 0;
}