📄 sdla_x25.c
字号:
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{ dev_kfree_skb_any(skb); ++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; chan->ifstats.rx_bytes += skb->len; ++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, struct net_device *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! */ dev_kfree_skb_any(new_skb); 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){ struct net_device *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 (netif_queue_stopped(dev)){ if (chan->common.usedby == API){ netif_start_queue(dev); wakeup_sk_bh(dev); }else{ netif_wake_queue(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 * * *===============================================================*/struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev){ if (card->u.x.no_dev != 1){ if (!*((struct net_device **)dev->priv)) return card->wandev.dev; else return *((struct net_device **)dev->priv); } return dev;}/*=============================================================== * tx_intr_send * * *===============================================================*/static int tx_intr_send(sdla_t *card, struct net_device *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 (netif_queue_stopped(dev)){ if (chan->common.usedby == API){ netif_start_queue(dev); wakeup_sk_bh(dev); }else{ netif_wake_queue(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) { struct net_device *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){ struct net_device *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; TX25ModemStatus *modem_status; struct net_device *dev; x25_channel_t *chan; int err; memset(&mbox->cmd, 0, sizeof(TX25Cmd)); mbox->cmd.command = X25_READ_MODEM_STATUS; err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; if (err){ x25_error(card, err, X25_READ_MODEM_STATUS, 0); }else{ modem_status = (TX25ModemStatus*)mbox->data; /* Check if the last status was the same * if it was, do NOT print message again */ if (last_stat.status != modem_status->status){ printk(KERN_INFO "%s: Modem Status Change: DCD=%s, CTS=%s\n", card->devname,DCD(modem_status->status),CTS(modem_status->status)); last_stat.status = modem_status->status; if (card->u.x.oob_on_modem){ mbox->cmd.pktType = mbox->cmd.command; mbox->cmd.result = 0x08; /* Send a OOB to all connected sockets */ for (dev = card->wandev.dev; dev; dev = *((struct net_device**)dev->priv)) { chan=dev->priv; if (chan->common.usedby == API){ send_oob_msg(card,dev,mbox); } } /* The modem OOB message will probably kill the * the link. If we don't clear the flag here, * a deadlock could occur */ if (atomic_read(&card->u.x.command_busy)){ atomic_set(&card->u.x.command_busy,0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -