📄 hfc_pci.c
字号:
skb_queue_tail(&bcs->rqueue, skb); hfcpci_sched_event(bcs, B_RCVBUFREADY); } *z2r = new_z2; /* new position */ return (1);} /* hfcpci_empty_fifo_trans *//**********************************//* B-channel main receive routine *//**********************************/static voidmain_rec_hfcpci(struct BCState *bcs){ struct IsdnCardState *cs = bcs->cs; int rcnt, real_fifo; int receive, count = 5; struct sk_buff *skb; bzfifo_type *bz; u_char *bdata; z_type *zp; if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) { bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2; bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2; real_fifo = 1; } else { bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1; bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b1; real_fifo = 0; } Begin: count--; if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { debugl1(cs, "rec_data %d blocked", bcs->channel); return; } if (bz->f1 != bz->f2) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci rec %d f1(%d) f2(%d)", bcs->channel, bz->f1, bz->f2); zp = &bz->za[bz->f2]; rcnt = zp->z1 - zp->z2; if (rcnt < 0) rcnt += B_FIFO_SIZE; rcnt++; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci rec %d z1(%x) z2(%x) cnt(%d)", bcs->channel, zp->z1, zp->z2, rcnt); if ((skb = hfcpci_empty_fifo(bcs, bz, bdata, rcnt))) { skb_queue_tail(&bcs->rqueue, skb); hfcpci_sched_event(bcs, B_RCVBUFREADY); } rcnt = bz->f1 - bz->f2; if (rcnt < 0) rcnt += MAX_B_FRAMES + 1; if (cs->hw.hfcpci.last_bfifo_cnt[real_fifo] > rcnt + 1) { rcnt = 0; hfcpci_clear_fifo_rx(cs, real_fifo); } cs->hw.hfcpci.last_bfifo_cnt[real_fifo] = rcnt; if (rcnt > 1) receive = 1; else receive = 0; } else if (bcs->mode == L1_MODE_TRANS) receive = hfcpci_empty_fifo_trans(bcs, bz, bdata); else receive = 0; test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); if (count && receive) goto Begin; return;}/**************************//* D-channel send routine *//**************************/static voidhfcpci_fill_dfifo(struct IsdnCardState *cs){ int fcnt; int count, new_z1, maxlen; dfifo_type *df; u_char *src, *dst, new_f1; if (!cs->tx_skb) return; if (cs->tx_skb->len <= 0) return; df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_tx; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci_fill_Dfifo f1(%d) f2(%d) z1(f1)(%x)", df->f1, df->f2, df->za[df->f1 & D_FREG_MASK].z1); fcnt = df->f1 - df->f2; /* frame count actually buffered */ if (fcnt < 0) fcnt += (MAX_D_FRAMES + 1); /* if wrap around */ if (fcnt > (MAX_D_FRAMES - 1)) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci_fill_Dfifo more as 14 frames");#ifdef ERROR_STATISTIC cs->err_tx++;#endif return; } /* now determine free bytes in FIFO buffer */ count = df->za[df->f2 & D_FREG_MASK].z2 - df->za[df->f1 & D_FREG_MASK].z1 - 1; if (count <= 0) count += D_FIFO_SIZE; /* count now contains available bytes */ if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci_fill_Dfifo count(%ld/%d)", cs->tx_skb->len, count); if (count < cs->tx_skb->len) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci_fill_Dfifo no fifo mem"); return; } count = cs->tx_skb->len; /* get frame len */ new_z1 = (df->za[df->f1 & D_FREG_MASK].z1 + count) & (D_FIFO_SIZE - 1); new_f1 = ((df->f1 + 1) & D_FREG_MASK) | (D_FREG_MASK + 1); src = cs->tx_skb->data; /* source pointer */ dst = df->data + df->za[df->f1 & D_FREG_MASK].z1; maxlen = D_FIFO_SIZE - df->za[df->f1 & D_FREG_MASK].z1; /* end fifo */ if (maxlen > count) maxlen = count; /* limit size */ memcpy(dst, src, maxlen); /* first copy */ count -= maxlen; /* remaining bytes */ if (count) { dst = df->data; /* start of buffer */ src += maxlen; /* new position */ memcpy(dst, src, count); } df->za[new_f1 & D_FREG_MASK].z1 = new_z1; /* for next buffer */ df->za[df->f1 & D_FREG_MASK].z1 = new_z1; /* new pos actual buffer */ df->f1 = new_f1; /* next frame */ dev_kfree_skb_any(cs->tx_skb); cs->tx_skb = NULL; return;}/**************************//* B-channel send routine *//**************************/static voidhfcpci_fill_fifo(struct BCState *bcs){ struct IsdnCardState *cs = bcs->cs; int maxlen, fcnt; int count, new_z1; bzfifo_type *bz; u_char *bdata; u_char new_f1, *src, *dst; unsigned short *z1t, *z2t; if (!bcs->tx_skb) return; if (bcs->tx_skb->len <= 0) return; if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) { bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2; bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txdat_b2; } else { bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1; bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txdat_b1; } if (bcs->mode == L1_MODE_TRANS) { z1t = &bz->za[MAX_B_FRAMES].z1; z2t = z1t + 1; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_fifo_trans %d z1(%x) z2(%x)", bcs->channel, *z1t, *z2t); fcnt = *z2t - *z1t; if (fcnt <= 0) fcnt += B_FIFO_SIZE; /* fcnt contains available bytes in fifo */ fcnt = B_FIFO_SIZE - fcnt; /* remaining bytes to send */ while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) { if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) { /* data is suitable for fifo */ count = bcs->tx_skb->len; new_z1 = *z1t + count; /* new buffer Position */ if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL)) new_z1 -= B_FIFO_SIZE; /* buffer wrap */ src = bcs->tx_skb->data; /* source pointer */ dst = bdata + (*z1t - B_SUB_VAL); maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t; /* end of fifo */ if (maxlen > count) maxlen = count; /* limit size */ memcpy(dst, src, maxlen); /* first copy */ count -= maxlen; /* remaining bytes */ if (count) { dst = bdata; /* start of buffer */ src += maxlen; /* new position */ memcpy(dst, src, count); } bcs->tx_cnt -= bcs->tx_skb->len; fcnt += bcs->tx_skb->len; *z1t = new_z1; /* now send data */ } else if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded", bcs->channel, bcs->tx_skb->len); if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && (PACKET_NOACK != bcs->tx_skb->pkt_type)) { u_long flags; spin_lock_irqsave(&bcs->aclock, flags); bcs->ackcnt += bcs->tx_skb->len; spin_unlock_irqrestore(&bcs->aclock, flags); schedule_event(bcs, B_ACKPENDING); } dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */ } test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); return; } if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_fifo_hdlc %d f1(%d) f2(%d) z1(f1)(%x)", bcs->channel, bz->f1, bz->f2, bz->za[bz->f1].z1); fcnt = bz->f1 - bz->f2; /* frame count actually buffered */ if (fcnt < 0) fcnt += (MAX_B_FRAMES + 1); /* if wrap around */ if (fcnt > (MAX_B_FRAMES - 1)) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_Bfifo more as 14 frames"); return; } /* now determine free bytes in FIFO buffer */ count = bz->za[bz->f2].z2 - bz->za[bz->f1].z1 - 1; if (count <= 0) count += B_FIFO_SIZE; /* count now contains available bytes */ if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_fifo %d count(%ld/%d),%lx", bcs->channel, bcs->tx_skb->len, count, current->state); if (count < bcs->tx_skb->len) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_fifo no fifo mem"); return; } count = bcs->tx_skb->len; /* get frame len */ new_z1 = bz->za[bz->f1].z1 + count; /* new buffer Position */ if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL)) new_z1 -= B_FIFO_SIZE; /* buffer wrap */ new_f1 = ((bz->f1 + 1) & MAX_B_FRAMES); src = bcs->tx_skb->data; /* source pointer */ dst = bdata + (bz->za[bz->f1].z1 - B_SUB_VAL); maxlen = (B_FIFO_SIZE + B_SUB_VAL) - bz->za[bz->f1].z1; /* end fifo */ if (maxlen > count) maxlen = count; /* limit size */ memcpy(dst, src, maxlen); /* first copy */ count -= maxlen; /* remaining bytes */ if (count) { dst = bdata; /* start of buffer */ src += maxlen; /* new position */ memcpy(dst, src, count); } bcs->tx_cnt -= bcs->tx_skb->len; if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && (PACKET_NOACK != bcs->tx_skb->pkt_type)) { u_long flags; spin_lock_irqsave(&bcs->aclock, flags); bcs->ackcnt += bcs->tx_skb->len; spin_unlock_irqrestore(&bcs->aclock, flags); schedule_event(bcs, B_ACKPENDING); } bz->za[new_f1].z1 = new_z1; /* for next buffer */ bz->f1 = new_f1; /* next frame */ dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); return;}/**********************************************//* D-channel l1 state call for leased NT-mode *//**********************************************/static voiddch_nt_l2l1(struct PStack *st, int pr, void *arg){ struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; switch (pr) { case (PH_DATA | REQUEST): case (PH_PULL | REQUEST): case (PH_PULL | INDICATION): st->l1.l1hw(st, pr, arg); break; case (PH_ACTIVATE | REQUEST): st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); break; case (PH_TESTLOOP | REQUEST): if (1 & (long) arg) debugl1(cs, "PH_TEST_LOOP B1"); if (2 & (long) arg) debugl1(cs, "PH_TEST_LOOP B2"); if (!(3 & (long) arg)) debugl1(cs, "PH_TEST_LOOP DISABLED"); st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg); break; default: if (cs->debug) debugl1(cs, "dch_nt_l2l1 msg %04X unhandled", pr); break; }}/***********************//* set/reset echo mode *//***********************/static inthfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic){ u_long flags; int i = *(unsigned int *) ic->parm.num; if ((ic->arg == 98) && (!(cs->hw.hfcpci.int_m1 & (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC + HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC)))) { spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCPCI_CLKDEL, CLKDEL_NT); /* ST-Bit delay for NT-Mode */ Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 0); /* HFC ST G0 */ udelay(10); cs->hw.hfcpci.sctrl |= SCTRL_MODE_NT; Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); /* set NT-mode */ udelay(10); Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 1); /* HFC ST G1 */ udelay(10); Write_hfc(cs, HFCPCI_STATES, 1 | HFCPCI_ACTIVATE | HFCPCI_DO_ACTION); cs->dc.hfcpci.ph_state = 1; cs->hw.hfcpci.nt_mode = 1; cs->hw.hfcpci.nt_timer = 0; cs->stlist->l2.l2l1 = dch_nt_l2l1; spin_unlock_irqrestore(&cs->lock, flags); debugl1(cs, "NT mode activated"); return (0); } if ((cs->chanlimit > 1) || (cs->hw.hfcpci.bswapped) || (cs->hw.hfcpci.nt_mode) || (ic->arg != 12)) return (-EINVAL); spin_lock_irqsave(&cs->lock, flags); if (i) { cs->logecho = 1; cs->hw.hfcpci.trm |= 0x20; /* enable echo chan */ cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_B2REC; cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2RX; } else { cs->logecho = 0; cs->hw.hfcpci.trm &= ~0x20; /* disable echo chan */ cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_B2REC; cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2RX; } cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA; cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA; cs->hw.hfcpci.conn |= 0x10; /* B2-IOM -> B2-ST */ cs->hw.hfcpci.ctmt &= ~2; Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt); Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r); Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); spin_unlock_irqrestore(&cs->lock, flags); return (0);} /* hfcpci_auxcmd *//*****************************//* E-channel receive routine *//*****************************/static voidreceive_emsg(struct IsdnCardState *cs){ int rcnt; int receive, count = 5; bzfifo_type *bz; u_char *bdata; z_type *zp; u_char *ptr, *ptr1, new_f2; int total, maxlen, new_z2; u_char e_buffer[256]; bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2; bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2; Begin: count--; if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { debugl1(cs, "echo_rec_data blocked"); return; } if (bz->f1 != bz->f2) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci e_rec f1(%d) f2(%d)", bz->f1, bz->f2); zp = &bz->za[bz->f2]; rcnt = zp->z1 - zp->z2; if (rcnt < 0) rcnt += B_FIFO_SIZE; rcnt++; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci e_rec z1(%x) z2(%x) cnt(%d)", zp->z1, zp->z2, rcnt); new_z2 = zp->z2 + rcnt; /* new position in fifo */ if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) new_z2 -= B_FIFO_SIZE; /* buffer wrap */ new_f2 = (bz->f2 + 1) & MAX_B_FRAMES; if ((rcnt > 256 + 3) || (count < 4) || (*(bdata + (zp->z1 - B_SUB_VAL)))) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt); bz->za[new_f2].z2 = new_z2; bz->f2 = new_f2; /* next buffer */ } else { total = rcnt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -