📄 avm_pci.c
字号:
spin_lock_irqsave(&bcs->aclock, flags); bcs->ackcnt += bcs->hw.hdlc.count; spin_unlock_irqrestore(&bcs->aclock, flags); schedule_event(bcs, B_ACKPENDING); } dev_kfree_skb_irq(bcs->tx_skb); bcs->hw.hdlc.count = 0; bcs->tx_skb = NULL; } } if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { bcs->hw.hdlc.count = 0; test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); hdlc_fill_fifo(bcs); } else { test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); schedule_event(bcs, B_XMTBUFREADY); } }}static inline voidHDLC_irq_main(struct IsdnCardState *cs){ u_int stat; struct BCState *bcs; if (cs->subtyp == AVM_FRITZ_PCI) { stat = ReadHDLCPCI(cs, 0, HDLC_STATUS); } else { stat = ReadHDLCPnP(cs, 0, HDLC_STATUS); if (stat & HDLC_INT_RPR) stat |= (ReadHDLCPnP(cs, 0, HDLC_STATUS+1))<<8; } if (stat & HDLC_INT_MASK) { if (!(bcs = Sel_BCS(cs, 0))) { if (cs->debug) debugl1(cs, "hdlc spurious channel 0 IRQ"); } else HDLC_irq(bcs, stat); } if (cs->subtyp == AVM_FRITZ_PCI) { stat = ReadHDLCPCI(cs, 1, HDLC_STATUS); } else { stat = ReadHDLCPnP(cs, 1, HDLC_STATUS); if (stat & HDLC_INT_RPR) stat |= (ReadHDLCPnP(cs, 1, HDLC_STATUS+1))<<8; } if (stat & HDLC_INT_MASK) { if (!(bcs = Sel_BCS(cs, 1))) { if (cs->debug) debugl1(cs, "hdlc spurious channel 1 IRQ"); } else HDLC_irq(bcs, stat); }}static voidhdlc_l2l1(struct PStack *st, int pr, void *arg){ struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; u_long flags; switch (pr) { case (PH_DATA | REQUEST): spin_lock_irqsave(&bcs->cs->lock, flags); if (bcs->tx_skb) { skb_queue_tail(&bcs->squeue, skb); } else { bcs->tx_skb = skb; test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); bcs->hw.hdlc.count = 0; bcs->cs->BC_Send_Data(bcs); } spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): spin_lock_irqsave(&bcs->cs->lock, flags); if (bcs->tx_skb) { printk(KERN_WARNING "hdlc_l2l1: this shouldn't happen\n"); } else { test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); bcs->tx_skb = skb; bcs->hw.hdlc.count = 0; bcs->cs->BC_Send_Data(bcs); } spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): if (!bcs->tx_skb) { test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); } else test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): spin_lock_irqsave(&bcs->cs->lock, flags); test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); modehdlc(bcs, st->l1.mode, st->l1.bc); spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): spin_lock_irqsave(&bcs->cs->lock, flags); test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); modehdlc(bcs, 0, st->l1.bc); spin_unlock_irqrestore(&bcs->cs->lock, flags); st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; }}static voidclose_hdlcstate(struct BCState *bcs){ modehdlc(bcs, 0, 0); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { kfree(bcs->hw.hdlc.rcvbuf); bcs->hw.hdlc.rcvbuf = NULL; kfree(bcs->blog); bcs->blog = NULL; skb_queue_purge(&bcs->rqueue); skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } }}static intopen_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs){ if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { if (!(bcs->hw.hdlc.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { printk(KERN_WARNING "HiSax: No memory for hdlc.rcvbuf\n"); return (1); } if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { printk(KERN_WARNING "HiSax: No memory for bcs->blog\n"); test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); kfree(bcs->hw.hdlc.rcvbuf); bcs->hw.hdlc.rcvbuf = NULL; return (2); } skb_queue_head_init(&bcs->rqueue); skb_queue_head_init(&bcs->squeue); } bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->event = 0; bcs->hw.hdlc.rcvidx = 0; bcs->tx_cnt = 0; return (0);}static intsetstack_hdlc(struct PStack *st, struct BCState *bcs){ bcs->channel = st->l1.bc; if (open_hdlcstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; st->l2.l2l1 = hdlc_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); return (0);}#if 0void __initclear_pending_hdlc_ints(struct IsdnCardState *cs){ u_int val; if (cs->subtyp == AVM_FRITZ_PCI) { val = ReadHDLCPCI(cs, 0, HDLC_STATUS); debugl1(cs, "HDLC 1 STA %x", val); val = ReadHDLCPCI(cs, 1, HDLC_STATUS); debugl1(cs, "HDLC 2 STA %x", val); } else { val = ReadHDLCPnP(cs, 0, HDLC_STATUS); debugl1(cs, "HDLC 1 STA %x", val); val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 1); debugl1(cs, "HDLC 1 RML %x", val); val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 2); debugl1(cs, "HDLC 1 MODE %x", val); val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 3); debugl1(cs, "HDLC 1 VIN %x", val); val = ReadHDLCPnP(cs, 1, HDLC_STATUS); debugl1(cs, "HDLC 2 STA %x", val); val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 1); debugl1(cs, "HDLC 2 RML %x", val); val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 2); debugl1(cs, "HDLC 2 MODE %x", val); val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 3); debugl1(cs, "HDLC 2 VIN %x", val); }}#endif /* 0 */static void __initinithdlc(struct IsdnCardState *cs){ cs->bcs[0].BC_SetStack = setstack_hdlc; cs->bcs[1].BC_SetStack = setstack_hdlc; cs->bcs[0].BC_Close = close_hdlcstate; cs->bcs[1].BC_Close = close_hdlcstate; modehdlc(cs->bcs, -1, 0); modehdlc(cs->bcs + 1, -1, 1);}static irqreturn_tavm_pcipnp_interrupt(int intno, void *dev_id, struct pt_regs *regs){ struct IsdnCardState *cs = dev_id; u_long flags; u_char val; u_char sval; spin_lock_irqsave(&cs->lock, flags); sval = inb(cs->hw.avm.cfg_reg + 2); if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) { /* possible a shared IRQ reqest */ spin_unlock_irqrestore(&cs->lock, flags); return IRQ_NONE; } if (!(sval & AVM_STATUS0_IRQ_ISAC)) { val = ReadISAC(cs, ISAC_ISTA); isac_interrupt(cs, val); } if (!(sval & AVM_STATUS0_IRQ_HDLC)) { HDLC_irq_main(cs); } WriteISAC(cs, ISAC_MASK, 0xFF); WriteISAC(cs, ISAC_MASK, 0x0); spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED;}static voidreset_avmpcipnp(struct IsdnCardState *cs){ printk(KERN_INFO "AVM PCI/PnP: reset\n"); outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2); mdelay(10); outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2); outb(AVM_STATUS1_ENA_IOM | cs->irq, cs->hw.avm.cfg_reg + 3); mdelay(10); printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3));}static intAVM_card_msg(struct IsdnCardState *cs, int mt, void *arg){ u_long flags; switch (mt) { case CARD_RESET: spin_lock_irqsave(&cs->lock, flags); reset_avmpcipnp(cs); spin_unlock_irqrestore(&cs->lock, flags); return(0); case CARD_RELEASE: outb(0, cs->hw.avm.cfg_reg + 2); release_region(cs->hw.avm.cfg_reg, 32); return(0); case CARD_INIT: spin_lock_irqsave(&cs->lock, flags); reset_avmpcipnp(cs); clear_pending_isac_ints(cs); initisac(cs); inithdlc(cs); outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER, cs->hw.avm.cfg_reg + 2); WriteISAC(cs, ISAC_MASK, 0); outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2); /* RESET Receiver and Transmitter */ WriteISAC(cs, ISAC_CMDR, 0x41); spin_unlock_irqrestore(&cs->lock, flags); return(0); case CARD_TEST: return(0); } return(0);}#ifdef CONFIG_PCIstatic struct pci_dev *dev_avm __initdata = NULL;#endif#ifdef __ISAPNP__static struct pnp_card *pnp_avm_c __initdata = NULL;#endifint __initsetup_avm_pcipnp(struct IsdnCard *card){ u_int val, ver; struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, avm_pci_rev); printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp)); if (cs->typ != ISDN_CTYPE_FRITZPCI) return (0); if (card->para[1]) { /* old manual method */ cs->hw.avm.cfg_reg = card->para[1]; cs->irq = card->para[0]; cs->subtyp = AVM_FRITZ_PNP; goto ready; }#ifdef __ISAPNP__ if (isapnp_present()) { struct pnp_dev *pnp_avm_d = NULL; if ((pnp_avm_c = pnp_find_card( ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900), pnp_avm_c))) { if ((pnp_avm_d = pnp_find_dev(pnp_avm_c, ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900), pnp_avm_d))) { int err; pnp_disable_dev(pnp_avm_d); err = pnp_activate_dev(pnp_avm_d); if (err<0) { printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", __FUNCTION__, err); return(0); } cs->hw.avm.cfg_reg = pnp_port_start(pnp_avm_d, 0); cs->irq = pnp_irq(pnp_avm_d, 0); if (!cs->irq) { printk(KERN_ERR "FritzPnP:No IRQ\n"); return(0); } if (!cs->hw.avm.cfg_reg) { printk(KERN_ERR "FritzPnP:No IO address\n"); return(0); } cs->subtyp = AVM_FRITZ_PNP; goto ready; } } } else { printk(KERN_INFO "FritzPnP: no ISA PnP present\n"); }#endif#ifdef CONFIG_PCI if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, dev_avm))) { if (pci_enable_device(dev_avm)) return(0); cs->irq = dev_avm->irq; if (!cs->irq) { printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n"); return(0); } cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1); if (!cs->hw.avm.cfg_reg) { printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n"); return(0); } cs->subtyp = AVM_FRITZ_PCI; } else { printk(KERN_WARNING "FritzPCI: No PCI card found\n"); return(0); } cs->irq_flags |= SA_SHIRQ;#else printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n"); return (0);#endif /* CONFIG_PCI */ready: cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; if (!request_region(cs->hw.avm.cfg_reg, 32, (cs->subtyp == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP")) { printk(KERN_WARNING "HiSax: %s config port %x-%x already in use\n", CardType[card->typ], cs->hw.avm.cfg_reg, cs->hw.avm.cfg_reg + 31); return (0); } switch (cs->subtyp) { case AVM_FRITZ_PCI: val = inl(cs->hw.avm.cfg_reg); printk(KERN_INFO "AVM PCI: stat %#x\n", val); printk(KERN_INFO "AVM PCI: Class %X Rev %d\n", val & 0xff, (val>>8) & 0xff); cs->BC_Read_Reg = &ReadHDLC_s; cs->BC_Write_Reg = &WriteHDLC_s; break; case AVM_FRITZ_PNP: val = inb(cs->hw.avm.cfg_reg); ver = inb(cs->hw.avm.cfg_reg + 1); printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver); cs->BC_Read_Reg = &ReadHDLCPnP; cs->BC_Write_Reg = &WriteHDLCPnP; break; default: printk(KERN_WARNING "AVM unknown subtype %d\n", cs->subtyp); return(0); } printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n", (cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP", cs->irq, cs->hw.avm.cfg_reg); setup_isac(cs); cs->readisac = &ReadISAC; cs->writeisac = &WriteISAC; cs->readisacfifo = &ReadISACfifo; cs->writeisacfifo = &WriteISACfifo; cs->BC_Send_Data = &hdlc_fill_fifo; cs->cardmsg = &AVM_card_msg; cs->irq_func = &avm_pcipnp_interrupt; cs->writeisac(cs, ISAC_MASK, 0xFF); ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:"); return (1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -