📄 hfc_pci.c
字号:
cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1; cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); } break; case (L1_MODE_TRANS): hfcpci_clear_fifo_rx(cs, fifo2); hfcpci_clear_fifo_tx(cs, fifo2); if (bc) { cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA; } else { cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA; } if (fifo2) { cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2; cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); cs->hw.hfcpci.ctmt |= 2; cs->hw.hfcpci.conn &= ~0x18; } else { cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1; cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); cs->hw.hfcpci.ctmt |= 1; cs->hw.hfcpci.conn &= ~0x03; } break; case (L1_MODE_HDLC): hfcpci_clear_fifo_rx(cs, fifo2); hfcpci_clear_fifo_tx(cs, fifo2); if (bc) { cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA; } else { cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA; } if (fifo2) { cs->hw.hfcpci.last_bfifo_cnt[1] = 0; cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2; cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); cs->hw.hfcpci.ctmt &= ~2; cs->hw.hfcpci.conn &= ~0x18; } else { cs->hw.hfcpci.last_bfifo_cnt[0] = 0; cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1; cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); cs->hw.hfcpci.ctmt &= ~1; cs->hw.hfcpci.conn &= ~0x03; } break; case (L1_MODE_EXTRN): if (bc) { cs->hw.hfcpci.conn |= 0x10; cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA; cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2; cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); } else { cs->hw.hfcpci.conn |= 0x02; cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA; cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1; cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); } break; } Write_hfc(cs, HFCPCI_SCTRL_E, cs->hw.hfcpci.sctrl_e); Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r); Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt); Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);}/******************************//* Layer2 -> Layer 1 Transfer *//******************************/static voidhfcpci_l2l1(struct PStack *st, int pr, void *arg){ struct BCState *bcs = st->l1.bcs; u_long flags; struct sk_buff *skb = arg; 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->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) { spin_unlock_irqrestore(&bcs->cs->lock, flags); printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); break; }// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); bcs->tx_skb = skb; 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); mode_hfcpci(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); mode_hfcpci(bcs, 0, st->l1.bc); spin_unlock_irqrestore(&bcs->cs->lock, flags); st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; }}/******************************************//* deactivate B-channel access and queues *//******************************************/static voidclose_hfcpci(struct BCState *bcs){ mode_hfcpci(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { 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); } }}/*************************************//* init B-channel queues and control *//*************************************/static intopen_hfcpcistate(struct IsdnCardState *cs, struct BCState *bcs){ if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { 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->tx_cnt = 0; return (0);}/*********************************//* inits the stack for B-channel *//*********************************/static intsetstack_2b(struct PStack *st, struct BCState *bcs){ bcs->channel = st->l1.bc; if (open_hfcpcistate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; st->l2.l2l1 = hfcpci_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); return (0);}/***************************//* handle L1 state changes *//***************************/static voidhfcpci_bh(struct IsdnCardState *cs){ u_long flags;// struct PStack *stptr; if (!cs) return; if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { if (!cs->hw.hfcpci.nt_mode) switch (cs->dc.hfcpci.ph_state) { case (0): l1_msg(cs, HW_RESET | INDICATION, NULL); break; case (3): l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); break; case (8): l1_msg(cs, HW_RSYNC | INDICATION, NULL); break; case (6): l1_msg(cs, HW_INFO2 | INDICATION, NULL); break; case (7): l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); break; default: break; } else { spin_lock_irqsave(&cs->lock, flags); switch (cs->dc.hfcpci.ph_state) { case (2): if (cs->hw.hfcpci.nt_timer < 0) { cs->hw.hfcpci.nt_timer = 0; cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); /* Clear already pending ints */ if (Read_hfc(cs, HFCPCI_INT_S1)); Write_hfc(cs, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE); udelay(10); Write_hfc(cs, HFCPCI_STATES, 4); cs->dc.hfcpci.ph_state = 4; } else { cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_TIMER; Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); cs->hw.hfcpci.ctmt &= ~HFCPCI_AUTO_TIMER; cs->hw.hfcpci.ctmt |= HFCPCI_TIM3_125; Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER); Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER); cs->hw.hfcpci.nt_timer = NT_T1_COUNT; Write_hfc(cs, HFCPCI_STATES, 2 | HFCPCI_NT_G2_G3); /* allow G2 -> G3 transition */ } break; case (1): case (3): case (4): cs->hw.hfcpci.nt_timer = 0; cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); break; default: break; } spin_unlock_irqrestore(&cs->lock, flags); } } if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) DChannel_proc_rcv(cs); if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) DChannel_proc_xmt(cs);}/********************************//* called for card init message *//********************************/static void __initinithfcpci(struct IsdnCardState *cs){ cs->bcs[0].BC_SetStack = setstack_2b; cs->bcs[1].BC_SetStack = setstack_2b; cs->bcs[0].BC_Close = close_hfcpci; cs->bcs[1].BC_Close = close_hfcpci; cs->dbusytimer.function = (void *) hfcpci_dbusy_timer; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); mode_hfcpci(cs->bcs, 0, 0); mode_hfcpci(cs->bcs + 1, 0, 1);}/*******************************************//* handle card messages from control layer *//*******************************************/static inthfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg){ u_long flags; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "HFCPCI: card_msg %x", mt); switch (mt) { case CARD_RESET: spin_lock_irqsave(&cs->lock, flags); reset_hfcpci(cs); spin_unlock_irqrestore(&cs->lock, flags); return (0); case CARD_RELEASE: release_io_hfcpci(cs); return (0); case CARD_INIT: spin_lock_irqsave(&cs->lock, flags); inithfcpci(cs); reset_hfcpci(cs); spin_unlock_irqrestore(&cs->lock, flags); msleep(80); /* Timeout 80ms */ /* now switch timer interrupt off */ spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); /* reinit mode reg */ Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); spin_unlock_irqrestore(&cs->lock, flags); return (0); case CARD_TEST: return (0); } return (0);}/* this variable is used as card index when more than one cards are present */static struct pci_dev *dev_hfcpci __initdata = NULL;#endif /* CONFIG_PCI */int __initsetup_hfcpci(struct IsdnCard *card){ u_long flags; struct IsdnCardState *cs = card->cs; char tmp[64]; int i; struct pci_dev *tmp_hfcpci = NULL;#ifdef __BIG_ENDIAN#error "not running on big endian machines now"#endif strcpy(tmp, hfcpci_revision); printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));#ifdef CONFIG_PCI cs->hw.hfcpci.int_s1 = 0; cs->dc.hfcpci.ph_state = 0; cs->hw.hfcpci.fifo = 255; if (cs->typ == ISDN_CTYPE_HFC_PCI) { i = 0; while (id_list[i].vendor_id) { tmp_hfcpci = pci_find_device(id_list[i].vendor_id, id_list[i].device_id, dev_hfcpci); i++; if (tmp_hfcpci) { if (pci_enable_device(tmp_hfcpci)) continue; pci_set_master(tmp_hfcpci); if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK))) continue; else break; } } if (tmp_hfcpci) { i--; dev_hfcpci = tmp_hfcpci; /* old device */ cs->hw.hfcpci.dev = dev_hfcpci; cs->irq = dev_hfcpci->irq; if (!cs->irq) { printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n"); return (0); } cs->hw.hfcpci.pci_io = (char *) dev_hfcpci->resource[ 1].start; printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name); } else { printk(KERN_WARNING "HFC-PCI: No PCI card found\n"); return (0); } if (!cs->hw.hfcpci.pci_io) { printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n"); return (0); } /* Allocate memory for FIFOS */ /* Because the HFC-PCI needs a 32K physical alignment, we */ /* need to allocate the double mem and align the address */ if (!(cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) { printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n"); return 0; } cs->hw.hfcpci.fifos = (void *) (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000; pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos)); cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256); printk(KERN_INFO "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", (u_int) cs->hw.hfcpci.pci_io, (u_int) cs->hw.hfcpci.fifos, (u_int) virt_to_bus(cs->hw.hfcpci.fifos), cs->irq, HZ); spin_lock_irqsave(&cs->lock, flags); pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */ cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */ cs->hw.hfcpci.int_m1 = 0; Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); /* At this point the needed PCI config is done */ /* fifos are still not enabled */ INIT_WORK(&cs->tqueue, (void *)(void *) hfcpci_bh, cs); cs->setstack_d = setstack_hfcpci; cs->BC_Send_Data = &hfcpci_send_data; cs->readisac = NULL; cs->writeisac = NULL; cs->readisacfifo = NULL; cs->writeisacfifo = NULL; cs->BC_Read_Reg = NULL; cs->BC_Write_Reg = NULL; cs->irq_func = &hfcpci_interrupt; cs->irq_flags |= SA_SHIRQ; cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer; cs->hw.hfcpci.timer.data = (long) cs; init_timer(&cs->hw.hfcpci.timer); cs->cardmsg = &hfcpci_card_msg; cs->auxcmd = &hfcpci_auxcmd; spin_unlock_irqrestore(&cs->lock, flags); return (1); } else return (0); /* no valid card type */#else printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n"); return (0);#endif /* CONFIG_PCI */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -