📄 hfc_pci.c
字号:
rcnt -= 3; ptr = e_buffer; if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL) maxlen = rcnt; /* complete transfer */ else maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */ ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */ memcpy(ptr, ptr1, maxlen); /* copy data */ rcnt -= maxlen; if (rcnt) { /* rest remaining */ ptr += maxlen; ptr1 = bdata; /* start of buffer */ memcpy(ptr, ptr1, rcnt); /* rest */ } bz->za[new_f2].z2 = new_z2; bz->f2 = new_f2; /* next buffer */ if (cs->debug & DEB_DLOG_HEX) { ptr = cs->dlog; if ((total - 3) < MAX_DLOG_SPACE / 3 - 10) { *ptr++ = 'E'; *ptr++ = 'C'; *ptr++ = 'H'; *ptr++ = 'O'; *ptr++ = ':'; ptr += QuickHex(ptr, e_buffer, total - 3); ptr--; *ptr++ = '\n'; *ptr = 0; HiSax_putstatus(cs, NULL, cs->dlog); } else HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3); } } rcnt = bz->f1 - bz->f2; if (rcnt < 0) rcnt += MAX_B_FRAMES + 1; if (rcnt > 1) receive = 1; else receive = 0; } else receive = 0; test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); if (count && receive) goto Begin; return;} /* receive_emsg *//*********************//* Interrupt handler *//*********************/static irqreturn_thfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs){ u_long flags; struct IsdnCardState *cs = dev_id; u_char exval; struct BCState *bcs; int count = 15; u_char val, stat; if (!(cs->hw.hfcpci.int_m2 & 0x08)) { debugl1(cs, "HFC-PCI: int_m2 %x not initialised", cs->hw.hfcpci.int_m2); return IRQ_NONE; /* not initialised */ } spin_lock_irqsave(&cs->lock, flags); if (HFCPCI_ANYINT & (stat = Read_hfc(cs, HFCPCI_STATUS))) { val = Read_hfc(cs, HFCPCI_INT_S1); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "HFC-PCI: stat(%02x) s1(%02x)", stat, val); } else { spin_unlock_irqrestore(&cs->lock, flags); return IRQ_NONE; } if (cs->debug & L1_DEB_ISAC) debugl1(cs, "HFC-PCI irq %x %s", val, test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? "locked" : "unlocked"); val &= cs->hw.hfcpci.int_m1; if (val & 0x40) { /* state machine irq */ exval = Read_hfc(cs, HFCPCI_STATES) & 0xf; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcpci.ph_state, exval); cs->dc.hfcpci.ph_state = exval; sched_event_D_pci(cs, D_L1STATECHANGE); val &= ~0x40; } if (val & 0x80) { /* timer irq */ if (cs->hw.hfcpci.nt_mode) { if ((--cs->hw.hfcpci.nt_timer) < 0) sched_event_D_pci(cs, D_L1STATECHANGE); } val &= ~0x80; Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER); } while (val) { if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { cs->hw.hfcpci.int_s1 |= val; spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } if (cs->hw.hfcpci.int_s1 & 0x18) { exval = val; val = cs->hw.hfcpci.int_s1; cs->hw.hfcpci.int_s1 = exval; } if (val & 0x08) { if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1 : 0))) { if (cs->debug) debugl1(cs, "hfcpci spurious 0x08 IRQ"); } else main_rec_hfcpci(bcs); } if (val & 0x10) { if (cs->logecho) receive_emsg(cs); else if (!(bcs = Sel_BCS(cs, 1))) { if (cs->debug) debugl1(cs, "hfcpci spurious 0x10 IRQ"); } else main_rec_hfcpci(bcs); } if (val & 0x01) { if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1 : 0))) { if (cs->debug) debugl1(cs, "hfcpci spurious 0x01 IRQ"); } else { if (bcs->tx_skb) { if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfcpci_fill_fifo(bcs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } else debugl1(cs, "fill_data %d blocked", bcs->channel); } else { if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfcpci_fill_fifo(bcs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } else debugl1(cs, "fill_data %d blocked", bcs->channel); } else { hfcpci_sched_event(bcs, B_XMTBUFREADY); } } } } if (val & 0x02) { if (!(bcs = Sel_BCS(cs, 1))) { if (cs->debug) debugl1(cs, "hfcpci spurious 0x02 IRQ"); } else { if (bcs->tx_skb) { if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfcpci_fill_fifo(bcs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } else debugl1(cs, "fill_data %d blocked", bcs->channel); } else { if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfcpci_fill_fifo(bcs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } else debugl1(cs, "fill_data %d blocked", bcs->channel); } else { hfcpci_sched_event(bcs, B_XMTBUFREADY); } } } } if (val & 0x20) { /* receive dframe */ receive_dmsg(cs); } if (val & 0x04) { /* dframe transmitted */ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) sched_event_D_pci(cs, D_CLEARBUSY); if (cs->tx_skb) { if (cs->tx_skb->len) { if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfcpci_fill_dfifo(cs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } else { debugl1(cs, "hfcpci_fill_dfifo irq blocked"); } goto afterXPR; } else { dev_kfree_skb_irq(cs->tx_skb); cs->tx_cnt = 0; cs->tx_skb = NULL; } } if ((cs->tx_skb = skb_dequeue(&cs->sq))) { cs->tx_cnt = 0; if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfcpci_fill_dfifo(cs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } else { debugl1(cs, "hfcpci_fill_dfifo irq blocked"); } } else sched_event_D_pci(cs, D_XMTBUFREADY); } afterXPR: if (cs->hw.hfcpci.int_s1 && count--) { val = cs->hw.hfcpci.int_s1; cs->hw.hfcpci.int_s1 = 0; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "HFC-PCI irq %x loop %d", val, 15 - count); } else val = 0; } spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED;}/********************************************************************//* timer callback for D-chan busy resolution. Currently no function *//********************************************************************/static voidhfcpci_dbusy_timer(struct IsdnCardState *cs){}/*************************************//* Layer 1 D-channel hardware access *//*************************************/static voidHFCPCI_l1hw(struct PStack *st, int pr, void *arg){ u_long flags; struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; switch (pr) { case (PH_DATA | REQUEST): if (cs->debug & DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len); if (cs->debug & DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0); spin_lock_irqsave(&cs->lock, flags); if (cs->tx_skb) { skb_queue_tail(&cs->sq, skb);#ifdef L2FRAME_DEBUG /* psa */ if (cs->debug & L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA Queued", 0);#endif } else { cs->tx_skb = skb; cs->tx_cnt = 0;#ifdef L2FRAME_DEBUG /* psa */ if (cs->debug & L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA", 0);#endif if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfcpci_fill_dfifo(cs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } else debugl1(cs, "hfcpci_fill_dfifo blocked"); } spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | INDICATION): spin_lock_irqsave(&cs->lock, flags); if (cs->tx_skb) { if (cs->debug & L1_DEB_WARN) debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); skb_queue_tail(&cs->sq, skb); spin_unlock_irqrestore(&cs->lock, flags); break; } if (cs->debug & DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len); if (cs->debug & DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0); cs->tx_skb = skb; cs->tx_cnt = 0;#ifdef L2FRAME_DEBUG /* psa */ if (cs->debug & L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);#endif if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfcpci_fill_dfifo(cs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } else debugl1(cs, "hfcpci_fill_dfifo blocked"); spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | REQUEST):#ifdef L2FRAME_DEBUG /* psa */ if (cs->debug & L1_DEB_LAPD) debugl1(cs, "-> PH_REQUEST_PULL");#endif if (!cs->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 (HW_RESET | REQUEST): spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 3); /* HFC ST 3 */ udelay(6); Write_hfc(cs, HFCPCI_STATES, 3); /* HFC ST 2 */ cs->hw.hfcpci.mst_m |= HFCPCI_MASTER; Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION); spin_unlock_irqrestore(&cs->lock, flags); l1_msg(cs, HW_POWERUP | CONFIRM, NULL); break; case (HW_ENABLE | REQUEST): spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCPCI_STATES, HFCPCI_DO_ACTION); spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_DEACTIVATE | REQUEST): spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER; Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_INFO3 | REQUEST): spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcpci.mst_m |= HFCPCI_MASTER; Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_TESTLOOP | REQUEST): spin_lock_irqsave(&cs->lock, flags); switch ((int) arg) { case (1): Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* tx slot */ Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* rx slot */ cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~7) | 1; Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); break; case (2): Write_hfc(cs, HFCPCI_B2_SSL, 0x81); /* tx slot */ Write_hfc(cs, HFCPCI_B2_RSL, 0x81); /* rx slot */ cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~0x38) | 0x08; Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); break; default: spin_unlock_irqrestore(&cs->lock, flags); if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfcpci_l1hw loop invalid %4x", (int) arg); return; } cs->hw.hfcpci.trm |= 0x80; /* enable IOM-loop */ Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); spin_unlock_irqrestore(&cs->lock, flags); break; default: if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfcpci_l1hw unknown pr %4x", pr); break; }}/***********************************************//* called during init setting l1 stack pointer *//***********************************************/static voidsetstack_hfcpci(struct PStack *st, struct IsdnCardState *cs){ st->l1.l1hw = HFCPCI_l1hw;}/**************************************//* send B-channel data if not blocked *//**************************************/static voidhfcpci_send_data(struct BCState *bcs){ struct IsdnCardState *cs = bcs->cs; if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfcpci_fill_fifo(bcs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } else debugl1(cs, "send_data %d blocked", bcs->channel);}/***************************************************************//* activate/deactivate hardware for selected channels and mode *//***************************************************************/static voidmode_hfcpci(struct BCState *bcs, int mode, int bc){ struct IsdnCardState *cs = bcs->cs; int fifo2; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "HFCPCI bchannel mode %d bchan %d/%d", mode, bc, bcs->channel); bcs->mode = mode; bcs->channel = bc; fifo2 = bc; if (cs->chanlimit > 1) { cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */ cs->hw.hfcpci.sctrl_e &= ~0x80; } else { if (bc) { if (mode != L1_MODE_NULL) { cs->hw.hfcpci.bswapped = 1; /* B1 and B2 exchanged */ cs->hw.hfcpci.sctrl_e |= 0x80; } else { cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */ cs->hw.hfcpci.sctrl_e &= ~0x80; } fifo2 = 0; } else { cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */ cs->hw.hfcpci.sctrl_e &= ~0x80; } } switch (mode) { case (L1_MODE_NULL): 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); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -