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; } }
/* * 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; }
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; }
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); } }
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); } }
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); } }
/* * 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; }
/* * 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); } }
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; } } } }
/* * 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; }
/* * 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; } }
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; }
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; }