📄 eicon_io.c
字号:
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); }}#ifdef CONFIG_ISDN_DRV_EICON_ISA/* * IRQ handler */voideicon_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;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -