📄 wanpipe_multppp.c
字号:
static void rx_intr (sdla_t* card){ struct net_device *dev; chdlc_private_area_t *chdlc_priv_area; SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; CHDLC_DATA_RX_STATUS_EL_STRUCT *rxbuf = card->u.c.rxmb; struct sk_buff *skb; unsigned len; unsigned addr = rxbuf->ptr_data_bfr; void *buf; int i,udp_type; if (rxbuf->opp_flag != 0x01) { printk(KERN_INFO "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", card->devname, (unsigned)rxbuf, rxbuf->opp_flag); printk(KERN_INFO "Code name: "); for(i = 0; i < 4; i ++) printk(KERN_INFO "%c", flags->global_info_struct.codename[i]); printk(KERN_INFO "\nCode version: "); for(i = 0; i < 4; i ++) printk(KERN_INFO "%c", flags->global_info_struct.codeversion[i]); printk(KERN_INFO "\n"); /* Bug Fix: Mar 6 2000 * If we get a corrupted mailbox, it measn that driver * is out of sync with the firmware. There is no recovery. * If we don't turn off all interrupts for this card * the machine will crash. */ printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname); printk(KERN_INFO "Please contact Sangoma Technologies !\n"); chdlc_set_intr_mode(card,0); return; } dev = card->wandev.dev; if (!dev){ goto rx_exit; } if (!netif_running(dev)){ goto rx_exit; } chdlc_priv_area = dev->priv; if (rxbuf->error_flag){ goto rx_exit; } /* Take off two CRC bytes */ if (rxbuf->frame_length < 7 || rxbuf->frame_length > 1506 ){ goto rx_exit; } len = rxbuf->frame_length - CRC_LENGTH; /* Allocate socket buffer */ skb = dev_alloc_skb(len); if (skb == NULL) { if (net_ratelimit()){ printk(KERN_INFO "%s: no socket buffers available!\n", card->devname); } ++card->wandev.stats.rx_dropped; goto rx_exit; } /* Copy data to the socket buffer */ if((addr + len) > card->u.c.rx_top + 1) { unsigned tmp = card->u.c.rx_top - addr + 1; buf = skb_put(skb, tmp); sdla_peek(&card->hw, addr, buf, tmp); addr = card->u.c.rx_base; len -= tmp; } buf = skb_put(skb, len); sdla_peek(&card->hw, addr, buf, len); skb->protocol = htons(ETH_P_WAN_PPP); card->wandev.stats.rx_packets ++; card->wandev.stats.rx_bytes += skb->len; udp_type = udp_pkt_type( skb, card ); if(udp_type == UDP_CPIPE_TYPE) { if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK, card, skb, dev, chdlc_priv_area)) { flags->interrupt_info_struct. interrupt_permission |= APP_INT_ON_TIMER; } }else{ /* Pass it up the protocol stack */ skb->dev = dev; skb->mac.raw = skb->data; netif_rx(skb); dev->last_rx = jiffies; }rx_exit: /* Release buffer element and calculate a pointer to the next one */ rxbuf->opp_flag = 0x00; card->u.c.rxmb = ++ rxbuf; if((void*)rxbuf > card->u.c.rxbuf_last){ card->u.c.rxmb = card->u.c.rxbuf_base; }}/*============================================================================ * Timer interrupt handler. * The timer interrupt is used for two purposes: * 1) Processing udp calls from 'cpipemon'. * 2) Reading board-level statistics for updating the proc file system. */void timer_intr(sdla_t *card){ struct net_device* dev; chdlc_private_area_t* chdlc_priv_area = NULL; SHARED_MEMORY_INFO_STRUCT* flags = NULL; dev = card->wandev.dev; chdlc_priv_area = dev->priv; if (chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG) { if (!config_chdlc(card)){ chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG; } } /* process a udp call if pending */ if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP) { process_udp_mgmt_pkt(card, dev, chdlc_priv_area); chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP; } /* read the communications statistics if required */ if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE) { update_comms_stats(card, chdlc_priv_area); if(!(-- chdlc_priv_area->update_comms_stats)) { chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE; } } /* only disable the timer interrupt if there are no udp or statistic */ /* updates pending */ if(!chdlc_priv_area->timer_int_enabled) { flags = card->u.c.flags; flags->interrupt_info_struct.interrupt_permission &= ~APP_INT_ON_TIMER; }}/*------------------------------------------------------------------------------ Miscellaneous Functions - set_chdlc_config() used to set configuration options on the board------------------------------------------------------------------------------*/static int set_chdlc_config(sdla_t* card){ CHDLC_CONFIGURATION_STRUCT cfg; memset(&cfg, 0, sizeof(CHDLC_CONFIGURATION_STRUCT)); if(card->wandev.clocking) cfg.baud_rate = card->wandev.bps; cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ? INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35; cfg.modem_config_options = 0; //API OPTIONS cfg.CHDLC_API_options = DISCARD_RX_ERROR_FRAMES; cfg.modem_status_timer = 100; cfg.CHDLC_protocol_options = HDLC_STREAMING_MODE; cfg.percent_data_buffer_for_Tx = 50; cfg.CHDLC_statistics_options = (CHDLC_TX_DATA_BYTE_COUNT_STAT | CHDLC_RX_DATA_BYTE_COUNT_STAT); cfg.max_CHDLC_data_field_length = card->wandev.mtu; cfg.transmit_keepalive_timer = 0; cfg.receive_keepalive_timer = 0; cfg.keepalive_error_tolerance = 0; cfg.SLARP_request_timer = 0; cfg.IP_address = 0; cfg.IP_netmask = 0; return chdlc_configure(card, &cfg);}/*============================================================================ * Process global exception condition */static int process_global_exception(sdla_t *card){ CHDLC_MAILBOX_STRUCT* mbox = card->mbox; int err; mbox->buffer_length = 0; mbox->command = READ_GLOBAL_EXCEPTION_CONDITION; err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT; if(err != CMD_TIMEOUT ){ switch(mbox->return_code) { case EXCEP_MODEM_STATUS_CHANGE: printk(KERN_INFO "%s: Modem status change\n", card->devname); switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) { case (DCD_HIGH): printk(KERN_INFO "%s: DCD high, CTS low\n",card->devname); break; case (CTS_HIGH): printk(KERN_INFO "%s: DCD low, CTS high\n",card->devname); break; case ((DCD_HIGH | CTS_HIGH)): printk(KERN_INFO "%s: DCD high, CTS high\n",card->devname); break; default: printk(KERN_INFO "%s: DCD low, CTS low\n",card->devname); break; } if (!(mbox->data[0] & DCD_HIGH) || !(mbox->data[0] & DCD_HIGH)){ //printk(KERN_INFO "Sending TERM Request Manually !\n"); send_ppp_term_request(card->wandev.dev); } break; case EXCEP_TRC_DISABLED: printk(KERN_INFO "%s: Line trace disabled\n", card->devname); break; case EXCEP_IRQ_TIMEOUT: printk(KERN_INFO "%s: IRQ timeout occurred\n", card->devname); break; default: printk(KERN_INFO "%s: Global exception %x\n", card->devname, mbox->return_code); break; } } return 0;}/*============================================================================ * Process chdlc exception condition */static int process_chdlc_exception(sdla_t *card){ CHDLC_MAILBOX_STRUCT* mb = card->mbox; int err; mb->buffer_length = 0; mb->command = READ_CHDLC_EXCEPTION_CONDITION; err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; if(err != CMD_TIMEOUT) { switch (err) { case EXCEP_LINK_ACTIVE: port_set_state(card, WAN_CONNECTED); break; case EXCEP_LINK_INACTIVE_MODEM: port_set_state(card, WAN_DISCONNECTED); break; case EXCEP_LOOPBACK_CONDITION: printk(KERN_INFO "%s: Loopback Condition Detected.\n", card->devname); break; case NO_CHDLC_EXCEP_COND_TO_REPORT: printk(KERN_INFO "%s: No exceptions reported.\n", card->devname); break; default: printk(KERN_INFO "%s: Exception Condition %x!\n", card->devname,err); break; } } return 0;}/*============================================================================= * Store a UDP management packet for later processing. */static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, struct sk_buff *skb, struct net_device* dev, chdlc_private_area_t* chdlc_priv_area ){ int udp_pkt_stored = 0; if(!chdlc_priv_area->udp_pkt_lgth && (skb->len <= MAX_LGTH_UDP_MGNT_PKT)) { chdlc_priv_area->udp_pkt_lgth = skb->len; chdlc_priv_area->udp_pkt_src = udp_pkt_src; memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len); chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP; udp_pkt_stored = 1; } if(udp_pkt_src == UDP_PKT_FRM_STACK) dev_kfree_skb_any(skb); else dev_kfree_skb_any(skb); return(udp_pkt_stored);}/*============================================================================= * Process UDP management packet. */static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev, chdlc_private_area_t* chdlc_priv_area ) { unsigned char *buf; unsigned int frames, len; struct sk_buff *new_skb; unsigned short buffer_length, real_len; unsigned long data_ptr; unsigned data_length; int udp_mgmt_req_valid = 1; CHDLC_MAILBOX_STRUCT *mb = card->mbox; SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; chdlc_udp_pkt_t *chdlc_udp_pkt; struct timeval tv; int err; char ut_char; chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data; if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) { switch(chdlc_udp_pkt->cblock.command) { case READ_GLOBAL_STATISTICS: case READ_MODEM_STATUS: case READ_CHDLC_LINK_STATUS: case CPIPE_ROUTER_UP_TIME: case READ_COMMS_ERROR_STATS: case READ_CHDLC_OPERATIONAL_STATS: /* These two commands are executed for * each request */ case READ_CHDLC_CONFIGURATION: case READ_CHDLC_CODE_VERSION: udp_mgmt_req_valid = 1; break; default: udp_mgmt_req_valid = 0; break; } } if(!udp_mgmt_req_valid) { /* set length to 0 */ chdlc_udp_pkt->cblock.buffer_length = 0; /* set return code */ chdlc_udp_pkt->cblock.return_code = 0xCD; if (net_ratelimit()){ printk(KERN_INFO "%s: Warning, Illegal UDP command attempted from network: %x\n", card->devname,chdlc_udp_pkt->cblock.command); } } else { unsigned long trace_status_cfg_addr = 0; TRACE_STATUS_EL_CFG_STRUCT trace_cfg_struct; TRACE_STATUS_ELEMENT_STRUCT trace_element_struct; switch(chdlc_udp_pkt->cblock.command) { case CPIPE_ENABLE_TRACING: if (!chdlc_priv_area->TracingEnabled) { /* OPERATE_DATALINE_MONITOR */ mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT); mb->command = SET_TRACE_CONFIGURATION; ((LINE_TRACE_CONFIG_STRUCT *)mb->data)-> trace_config = TRACE_ACTIVE; /* Trace delay mode is not used because it slows down transfer and results in a standoff situation when there is a lot of data */ /* Configure the Trace based on user inputs */ ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->trace_config |= chdlc_udp_pkt->data[0]; ((LINE_TRACE_CONFIG_STRUCT *)mb->data)-> trace_deactivation_timer = 4000; err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; if (err != COMMAND_OK) { chdlc_error(card,err,mb); card->TracingEnabled = 0; chdlc_udp_pkt->cblock.return_code = err; mb->buffer_length = 0; break; } /* Get the base address of the trace element list */ mb->buffer_length = 0; mb->command = READ_TRACE_CONFIGURATION; err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; if (err != COMMAND_OK) { chdlc_error(card,err,mb); chdlc_priv_area->TracingEnabled = 0; chdlc_udp_pkt->cblock.return_code = err; mb->buffer_length = 0; break; } trace_status_cfg_addr =((LINE_TRACE_CONFIG_STRUCT *) mb->data) -> ptr_trace_stat_el_cfg_struct; sdla_peek(&card->hw, trace_status_cfg_addr, &trace_cfg_struct, sizeof(trace_cfg_struct)); chdlc_priv_area->start_trace_addr = trace_cfg_struct.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -