📄 pc300_drv.c
字号:
*/void falc_remote_loop(pc300_t * card, int ch, int loop_on){ pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; uclong falcbase = card->hw.falcbase; if (loop_on) { // EVENT_FALC_ABNORMAL if (conf->media == IF_IFACE_T1) { /* Disable this interrupt as it may otherwise interfere with * other working boards. */ cpc_writeb(falcbase + F_REG(IMR0, ch), cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN); } falc_disable_comm(card, ch); // EVENT_FALC_ABNORMAL cpc_writeb(falcbase + F_REG(LIM1, ch), cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RL); pfalc->loop_active = 1; } else { cpc_writeb(falcbase + F_REG(LIM1, ch), cpc_readb(falcbase + F_REG(LIM1, ch)) & ~LIM1_RL); pfalc->sync = 0; cpc_writeb(falcbase + card->hw.cpld_reg2, cpc_readb(falcbase + card->hw.cpld_reg2) & ~(CPLD_REG2_FALC_LED2 << (2 * ch))); pfalc->active = 0; falc_issue_cmd(card, ch, CMDR_XRES); pfalc->loop_active = 0; }}/*---------------------------------------------------------------------------- * falc_local_loop *---------------------------------------------------------------------------- * Description: The local loopback mode disconnects the receive lines * RL1/RL2 resp. RDIP/RDIN from the receiver. Instead of the * signals coming from the line the data provided by system * interface are routed through the analog receiver back to * the system interface. The unipolar bit stream will be * undisturbed transmitted on the line. Receiver and transmitter * coding must be identical. *---------------------------------------------------------------------------- */void falc_local_loop(pc300_t * card, int ch, int loop_on){ pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; falc_t *pfalc = (falc_t *) & chan->falc; uclong falcbase = card->hw.falcbase; if (loop_on) { cpc_writeb(falcbase + F_REG(LIM0, ch), cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_LL); pfalc->loop_active = 1; } else { cpc_writeb(falcbase + F_REG(LIM0, ch), cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_LL); pfalc->loop_active = 0; }}/*---------------------------------------------------------------------------- * falc_payload_loop *---------------------------------------------------------------------------- * Description: This routine allows to enable/disable payload loopback. * When the payload loop is activated, the received 192 bits * of payload data will be looped back to the transmit * direction. The framing bits, CRC6 and DL bits are not * looped. They are originated by the FALC-LH transmitter. *---------------------------------------------------------------------------- */void falc_payload_loop(pc300_t * card, int ch, int loop_on){ pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; uclong falcbase = card->hw.falcbase; if (loop_on) { // EVENT_FALC_ABNORMAL if (conf->media == IF_IFACE_T1) { /* Disable this interrupt as it may otherwise interfere with * other working boards. */ cpc_writeb(falcbase + F_REG(IMR0, ch), cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN); } falc_disable_comm(card, ch); // EVENT_FALC_ABNORMAL cpc_writeb(falcbase + F_REG(FMR2, ch), cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_PLB); if (conf->media == IF_IFACE_T1) { cpc_writeb(falcbase + F_REG(FMR4, ch), cpc_readb(falcbase + F_REG(FMR4, ch)) | FMR4_TM); } else { cpc_writeb(falcbase + F_REG(FMR5, ch), cpc_readb(falcbase + F_REG(FMR5, ch)) | XSP_TT0); } falc_open_all_timeslots(card, ch); pfalc->loop_active = 2; } else { cpc_writeb(falcbase + F_REG(FMR2, ch), cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_PLB); if (conf->media == IF_IFACE_T1) { cpc_writeb(falcbase + F_REG(FMR4, ch), cpc_readb(falcbase + F_REG(FMR4, ch)) & ~FMR4_TM); } else { cpc_writeb(falcbase + F_REG(FMR5, ch), cpc_readb(falcbase + F_REG(FMR5, ch)) & ~XSP_TT0); } pfalc->sync = 0; cpc_writeb(falcbase + card->hw.cpld_reg2, cpc_readb(falcbase + card->hw.cpld_reg2) & ~(CPLD_REG2_FALC_LED2 << (2 * ch))); pfalc->active = 0; falc_issue_cmd(card, ch, CMDR_XRES); pfalc->loop_active = 0; }}/*---------------------------------------------------------------------------- * turn_off_xlu *---------------------------------------------------------------------------- * Description: Turns XLU bit off in the proper register *---------------------------------------------------------------------------- */void turn_off_xlu(pc300_t * card, int ch){ pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; uclong falcbase = card->hw.falcbase; if (conf->media == IF_IFACE_T1) { cpc_writeb(falcbase + F_REG(FMR5, ch), cpc_readb(falcbase + F_REG(FMR5, ch)) & ~FMR5_XLU); } else { cpc_writeb(falcbase + F_REG(FMR3, ch), cpc_readb(falcbase + F_REG(FMR3, ch)) & ~FMR3_XLU); }}/*---------------------------------------------------------------------------- * turn_off_xld *---------------------------------------------------------------------------- * Description: Turns XLD bit off in the proper register *---------------------------------------------------------------------------- */void turn_off_xld(pc300_t * card, int ch){ pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; uclong falcbase = card->hw.falcbase; if (conf->media == IF_IFACE_T1) { cpc_writeb(falcbase + F_REG(FMR5, ch), cpc_readb(falcbase + F_REG(FMR5, ch)) & ~FMR5_XLD); } else { cpc_writeb(falcbase + F_REG(FMR3, ch), cpc_readb(falcbase + F_REG(FMR3, ch)) & ~FMR3_XLD); }}/*---------------------------------------------------------------------------- * falc_generate_loop_up_code *---------------------------------------------------------------------------- * Description: This routine writes the proper FALC chip register in order * to generate a LOOP activation code over a T1/E1 line. *---------------------------------------------------------------------------- */void falc_generate_loop_up_code(pc300_t * card, int ch){ pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; uclong falcbase = card->hw.falcbase; if (conf->media == IF_IFACE_T1) { cpc_writeb(falcbase + F_REG(FMR5, ch), cpc_readb(falcbase + F_REG(FMR5, ch)) | FMR5_XLU); } else { cpc_writeb(falcbase + F_REG(FMR3, ch), cpc_readb(falcbase + F_REG(FMR3, ch)) | FMR3_XLU); } // EVENT_FALC_ABNORMAL if (conf->media == IF_IFACE_T1) { /* Disable this interrupt as it may otherwise interfere with * other working boards. */ cpc_writeb(falcbase + F_REG(IMR0, ch), cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN); } falc_disable_comm(card, ch); // EVENT_FALC_ABNORMAL pfalc->loop_gen = 1;}/*---------------------------------------------------------------------------- * falc_generate_loop_down_code *---------------------------------------------------------------------------- * Description: This routine writes the proper FALC chip register in order * to generate a LOOP deactivation code over a T1/E1 line. *---------------------------------------------------------------------------- */void falc_generate_loop_down_code(pc300_t * card, int ch){ pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; uclong falcbase = card->hw.falcbase; if (conf->media == IF_IFACE_T1) { cpc_writeb(falcbase + F_REG(FMR5, ch), cpc_readb(falcbase + F_REG(FMR5, ch)) | FMR5_XLD); } else { cpc_writeb(falcbase + F_REG(FMR3, ch), cpc_readb(falcbase + F_REG(FMR3, ch)) | FMR3_XLD); } pfalc->sync = 0; cpc_writeb(falcbase + card->hw.cpld_reg2, cpc_readb(falcbase + card->hw.cpld_reg2) & ~(CPLD_REG2_FALC_LED2 << (2 * ch))); pfalc->active = 0;// falc_issue_cmd(card, ch, CMDR_XRES); pfalc->loop_gen = 0;}/*---------------------------------------------------------------------------- * falc_pattern_test *---------------------------------------------------------------------------- * Description: This routine generates a pattern code and checks * it on the reception side. *---------------------------------------------------------------------------- */void falc_pattern_test(pc300_t * card, int ch, unsigned int activate){ pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; uclong falcbase = card->hw.falcbase; if (activate) { pfalc->prbs = 1; pfalc->bec = 0; if (conf->media == IF_IFACE_T1) { /* Disable local loop activation/deactivation detect */ cpc_writeb(falcbase + F_REG(IMR3, ch), cpc_readb(falcbase + F_REG(IMR3, ch)) | IMR3_LLBSC); } else { /* Disable local loop activation/deactivation detect */ cpc_writeb(falcbase + F_REG(IMR1, ch), cpc_readb(falcbase + F_REG(IMR1, ch)) | IMR1_LLBSC); } /* Activates generation and monitoring of PRBS * (Pseudo Random Bit Sequence) */ cpc_writeb(falcbase + F_REG(LCR1, ch), cpc_readb(falcbase + F_REG(LCR1, ch)) | LCR1_EPRM | LCR1_XPRBS); } else { pfalc->prbs = 0; /* Deactivates generation and monitoring of PRBS * (Pseudo Random Bit Sequence) */ cpc_writeb(falcbase + F_REG(LCR1, ch), cpc_readb(falcbase+F_REG(LCR1,ch)) & ~(LCR1_EPRM | LCR1_XPRBS)); if (conf->media == IF_IFACE_T1) { /* Enable local loop activation/deactivation detect */ cpc_writeb(falcbase + F_REG(IMR3, ch), cpc_readb(falcbase + F_REG(IMR3, ch)) & ~IMR3_LLBSC); } else { /* Enable local loop activation/deactivation detect */ cpc_writeb(falcbase + F_REG(IMR1, ch), cpc_readb(falcbase + F_REG(IMR1, ch)) & ~IMR1_LLBSC); } }}/*---------------------------------------------------------------------------- * falc_pattern_test_error *---------------------------------------------------------------------------- * Description: This routine returns the bit error counter value *---------------------------------------------------------------------------- */ucshort falc_pattern_test_error(pc300_t * card, int ch){ pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; falc_t *pfalc = (falc_t *) & chan->falc; return (pfalc->bec);}/**********************************//*** Net Interface Routines ***//**********************************/static voidcpc_trace(struct net_device *dev, struct sk_buff *skb_main, char rx_tx){ struct sk_buff *skb; if ((skb = dev_alloc_skb(10 + skb_main->len)) == NULL) { printk("%s: out of memory\n", dev->name); return; } skb_put(skb, 10 + skb_main->len); skb->dev = dev; skb->protocol = htons(ETH_P_CUST); skb->mac.raw = skb->data; skb->pkt_type = PACKET_HOST; skb->len = 10 + skb_main->len; memcpy(skb->data, dev->name, 5); skb->data[5] = '['; skb->data[6] = rx_tx; skb->data[7] = ']'; skb->data[8] = ':'; skb->data[9] = ' '; memcpy(&skb->data[10], skb_main->data, skb_main->len); netif_rx(skb);}void cpc_tx_timeout(struct net_device *dev){ pc300dev_t *d = (pc300dev_t *) dev->priv; pc300ch_t *chan = (pc300ch_t *) d->chan; pc300_t *card = (pc300_t *) chan->card; struct net_device_stats *stats = &d->hdlc->stats; int ch = chan->channel; uclong flags; ucchar ilar; stats->tx_errors++; stats->tx_aborted_errors++; CPC_LOCK(card, flags); if ((ilar = cpc_readb(card->hw.scabase + ILAR)) != 0) { printk("%s: ILAR=0x%x\n", dev->name, ilar); cpc_writeb(card->hw.scabase + ILAR, ilar); cpc_writeb(card->hw.scabase + DMER, 0x80); } if (card->hw.type == PC300_TE) { cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2, cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) & ~(CPLD_REG2_FALC_LED1 << (2 * ch))); } dev->trans_start = jiffies; CPC_UNLOCK(card, flags); netif_wake_queue(dev);}int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev){ pc300dev_t *d = (pc300dev_t *) dev->priv; pc300ch_t *chan = (pc300ch_t *) d->chan; pc300_t *card = (pc300_t *) chan->card; struct net_device_stats *stats = &d->hdlc->stats; int ch = chan->channel; uclong flags;#ifdef PC300_DEBUG_TX int i;#endif if (chan->conf.monitor) { /* In monitor mode no Tx is done: ignore packet */ dev_kfree_skb(skb); return 0; } else if (!netif_carrier_ok(dev)) { /* DCD must be OFF: drop packet */ dev_kfree_skb(skb); stats->tx_errors++; stats->tx_carrier_errors++; return 0; } else if (cpc_readb(card->hw.scabase + M_REG(ST3, ch)) & ST3_DCD) { printk("%s: DCD is OFF. Going administrative down.\n", dev->name); stats->tx_errors++; stats->tx_carrier_errors++; dev_kfree_skb(skb); netif_carrier_off(dev); CPC_LOCK(card, flags); cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_BUF_CLR); if (card->hw.type == PC300_TE) { cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2, cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) & ~(CPLD_REG2_FALC_LED1 << (2 * ch))); } CPC_UNLOCK(card, flags); netif_wake_queue(dev); return 0; } /* Write buffer to DMA buffers */ if (dma_buf_write(card, ch, (ucchar *) skb->data, skb->len) != 0) {// printk("%s: write error. Dropping TX packet.\n", dev->name); netif_stop_queue(dev); dev_kfree_skb(skb); stats->tx_errors++; stats->tx_dropped++; return 0; }#ifdef PC300_DEBUG_TX printk("%s T:", dev->name); for (i = 0; i < skb->len; i++) printk(" %02x", *(skb->data + i)); printk("\n");#endif if (d->trace_on) { cpc_trace(dev, skb, 'T'); } dev->trans_start = jiffies; /* Start transmission */ CPC_LOCK(card, flags); /* verify if it has more than one free descriptor */ if (card->chan[ch].nfree_tx_bd <= 1) { /* don't have so stop the queue */ netif_stop_queue(dev); } cpc_writel(card->hw.scabase + DTX_REG(EDAL, ch), TX_BD_ADDR(ch, chan->tx_next_bd)); cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_ENA);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -