📄 sdla_x25.c
字号:
} dev->last_rx = jiffies; /* timestamp */ /* ------------ API ----------------*/ if (chan->common.usedby == API){ if (bh_enqueue(dev, skb)){ ++chan->ifstats.rx_dropped; ++card->wandev.stats.rx_dropped; ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; wan_dev_kfree_skb(skb, FREE_READ); return; } ++chan->ifstats.rx_packets;#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.rx_bytes += skb->len;#endif chan->rx_skb = NULL; if (!test_and_set_bit(0, &chan->tq_working)){ wanpipe_queue_tq(&chan->common.wanpipe_task); wanpipe_mark_bh(); } return; } /* ------------- WANPIPE -------------------*/ /* set rx_skb to NULL so we won't access it later when kernel already owns it */ chan->rx_skb=NULL; /* Decapsulate packet, if necessary */ if (!skb->protocol && !wanrouter_type_trans(skb, dev)){ /* can't decapsulate packet */ wan_dev_kfree_skb(skb, FREE_READ); ++chan->ifstats.rx_errors; ++chan->ifstats.rx_dropped; ++card->wandev.stats.rx_dropped; ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; }else{ if( handle_IPXWAN(skb->data, chan->name, chan->enable_IPX, chan->network_number, skb->protocol)){ if( chan->enable_IPX ){ if(chan_send(dev, skb->data, skb->len,0)){ chan->tx_skb = skb; }else{ wan_dev_kfree_skb(skb, FREE_WRITE); ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; } }else{ /* increment IPX packet dropped statistic */ ++chan->ifstats.rx_dropped; ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; } }else{ skb->mac.raw = skb->data;#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.rx_bytes += skb->len;#endif ++chan->ifstats.rx_packets; ++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack; netif_rx(skb); } } return;}static int wanpipe_pull_data_in_skb (sdla_t *card, netdevice_t *dev, struct sk_buff **skb){ void *bufptr; TX25Mbox* rxmb = card->rxmb; unsigned len = rxmb->cmd.length; /* packet length */ unsigned qdm = rxmb->cmd.qdm; /* Q,D and M bits */ x25_channel_t *chan = dev->priv; struct sk_buff *new_skb = *skb; if (chan->common.usedby == WANPIPE){ if (chan->drop_sequence){ if (!(qdm & 0x01)){ chan->drop_sequence = 0; } return 1; } new_skb = chan->rx_skb; }else{ /* Add on the API header to the received * data */ len += sizeof(x25api_hdr_t); } if (new_skb == NULL){ int bufsize; if (chan->common.usedby == WANPIPE){ bufsize = (qdm & 0x01) ? dev->mtu : len; }else{ bufsize = len; } /* Allocate new socket buffer */ new_skb = dev_alloc_skb(bufsize + dev->hard_header_len); if (new_skb == NULL){ printk(KERN_INFO "%s: no socket buffers available!\n", card->devname); chan->drop_sequence = 1; /* set flag */ ++chan->ifstats.rx_dropped; return 1; } } if (skb_tailroom(new_skb) < len){ /* No room for the packet. Call off the whole thing! */ wan_dev_kfree_skb(new_skb, FREE_READ); if (chan->common.usedby == WANPIPE){ chan->rx_skb = NULL; if (qdm & 0x01){ chan->drop_sequence = 1; } } printk(KERN_INFO "%s: unexpectedly long packet sequence " "on interface %s!\n", card->devname, dev->name); ++chan->ifstats.rx_length_errors; return 1; } bufptr = skb_put(new_skb,len); if (chan->common.usedby == API){ /* Fill in the x25api header */ x25api_t * api_data = (x25api_t*)bufptr; api_data->hdr.qdm = rxmb->cmd.qdm; api_data->hdr.cause = rxmb->cmd.cause; api_data->hdr.diagn = rxmb->cmd.diagn; api_data->hdr.length = rxmb->cmd.length; memcpy(api_data->data, rxmb->data, rxmb->cmd.length); }else{ memcpy(bufptr, rxmb->data, len); } new_skb->dev = dev; if (chan->common.usedby == API){ new_skb->mac.raw = new_skb->data; new_skb->protocol = htons(X25_PROT); new_skb->pkt_type = WAN_PACKET_DATA; }else{ new_skb->protocol = chan->protocol; chan->rx_skb = new_skb; } /* If qdm bit is set, more data is coming * thus, exit and wait for more data before * sending the packet up. (Used by router only) */ if ((qdm & 0x01) && (chan->common.usedby == WANPIPE)) return 1; *skb = new_skb; return 0;}/*=============================================================== * tx_intr * * Transmit interrupt handler. * For each dev, check that there is something to send. * If data available, transmit. * *===============================================================*/static void tx_intr (sdla_t* card){ netdevice_t *dev; TX25Status* status = card->flags; unsigned char more_to_tx=0; x25_channel_t *chan=NULL; int i=0; if (card->u.x.tx_dev == NULL){ card->u.x.tx_dev = card->wandev.dev; } dev = card->u.x.tx_dev; for (;;){ chan = dev->priv; if (chan->transmit_length){ /* Device was set to transmit, check if the TX * buffers are available */ if (chan->common.state != WAN_CONNECTED){ chan->transmit_length = 0; atomic_set(&chan->common.driver_busy,0); chan->tx_offset=0; if (is_queue_stopped(dev)){ if (chan->common.usedby == API){ start_net_queue(dev); wakeup_sk_bh(dev); }else{ wake_net_dev(dev); } } dev = move_dev_to_next(card,dev); break; } if ((status->cflags[chan->ch_idx] & 0x40 || card->u.x.LAPB_hdlc) && (*card->u.x.hdlc_buf_status & 0x40) ){ /* Tx buffer available, we can send */ if (tx_intr_send(card, dev)){ more_to_tx=1; } /* If more than one interface present, move the * device pointer to the next interface, so on the * next TX interrupt we will try sending from it. */ dev = move_dev_to_next(card,dev); break; }else{ /* Tx buffers not available, but device set * the TX interrupt. Set more_to_tx and try * to transmit for other devices. */ more_to_tx=1; dev = move_dev_to_next(card,dev); } }else{ /* This device was not set to transmit, * go to next */ dev = move_dev_to_next(card,dev); } if (++i == card->u.x.no_dev){ if (!more_to_tx){ DBG_PRINTK(KERN_INFO "%s: Nothing to Send in TX INTR\n", card->devname); } break; } } //End of FOR card->u.x.tx_dev = dev; if (!more_to_tx){ /* if any other interfaces have transmit interrupts pending, */ /* do not disable the global transmit interrupt */ if (!(--card->u.x.tx_interrupts_pending)){ status->imask &= ~INTR_ON_TX_FRAME; } } return;}/*=============================================================== * move_dev_to_next * * *===============================================================*/netdevice_t * move_dev_to_next (sdla_t *card, netdevice_t *dev){ if (card->u.x.no_dev != 1){ if (*((netdevice_t**)dev->priv) == NULL){ return card->wandev.dev; }else{ return *((netdevice_t**)dev->priv); } } return dev;}/*=============================================================== * tx_intr_send * * *===============================================================*/static int tx_intr_send(sdla_t *card, netdevice_t *dev){ x25_channel_t* chan = dev->priv; if (chan_send (dev,chan->transmit_buffer,chan->transmit_length,1)){ /* Packet was split up due to its size, do not disable * tx_intr */ return 1; } chan->transmit_length=0; atomic_set(&chan->common.driver_busy,0); chan->tx_offset=0; /* If we are in API mode, wakeup the * sock BH handler, not the NET_BH */ if (is_queue_stopped(dev)){ if (chan->common.usedby == API){ start_net_queue(dev); wakeup_sk_bh(dev); }else{ wake_net_dev(dev); } } return 0;}/*=============================================================== * timer_intr * * Timer interrupt handler. * Check who called the timer interrupt and perform * action accordingly. * *===============================================================*/static void timer_intr (sdla_t *card){ TX25Status* status = card->flags; if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC){ if (timer_intr_cmd_exec(card) == 0){ card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_CMD_EXEC; } }else if(card->u.x.timer_int_enabled & TMR_INT_ENABLED_UDP_PKT) { if ((*card->u.x.hdlc_buf_status & 0x40) && card->u.x.udp_type == UDP_XPIPE_TYPE){ if(process_udp_mgmt_pkt(card)) { card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_UDP_PKT; } } }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_ACTIVE) { netdevice_t *dev = card->u.x.poll_device; x25_channel_t *chan = NULL; if (!dev){ card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_ACTIVE; return; } chan = dev->priv; printk(KERN_INFO "%s: Closing down Idle link %s on LCN %d\n", card->devname,chan->name,chan->common.lcn); chan->i_timeout_sofar = jiffies; chan_disc(dev); card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_ACTIVE; card->u.x.poll_device=NULL; }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_CONNECT_ON) { wanpipe_set_state(card, WAN_CONNECTED); if (card->u.x.LAPB_hdlc){ netdevice_t *dev = card->wandev.dev; set_chan_state(dev,WAN_CONNECTED); send_delayed_cmd_result(card,dev,card->mbox); } /* 0x8F enable all interrupts */ x25_set_intr_mode(card, INTR_ON_RX_FRAME| INTR_ON_TX_FRAME| INTR_ON_MODEM_STATUS_CHANGE| //INTR_ON_COMMAND_COMPLETE| X25_ASY_TRANS_INTR_PENDING | INTR_ON_TIMER | DIRECT_RX_INTR_USAGE ); status->imask &= ~INTR_ON_TX_FRAME; /* mask Tx interrupts */ card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_CONNECT_ON; }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_CONNECT_OFF) { //printk(KERN_INFO "Poll connect, Turning OFF\n"); disconnect(card); card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_CONNECT_OFF; }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_DISCONNECT) { //printk(KERN_INFO "POll disconnect, trying to connect\n"); connect(card); card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_DISCONNECT; }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_UPDATE){ if (*card->u.x.hdlc_buf_status & 0x40){ x25_get_err_stats(card); x25_get_stats(card); card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE; } } if(!card->u.x.timer_int_enabled){ //printk(KERN_INFO "Turning Timer Off \n"); status->imask &= ~INTR_ON_TIMER; }}/*==================================================================== * Modem status interrupt handler. *===================================================================*/static void status_intr (sdla_t* card){ /* Added to avoid Modem status message flooding */ static TX25ModemStatus last_stat; TX25Mbox* mbox = card->mbox;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -