📄 wanpipe_multppp.c
字号:
card->wandev.name,card->wandev.critical); ++card->wandev.stats.tx_dropped; start_net_queue(dev); goto if_send_crit_exit; } if (card->wandev.state != WAN_CONNECTED){ ++card->wandev.stats.tx_dropped; start_net_queue(dev); goto if_send_crit_exit; } if (chdlc_send(card, skb->data, skb->len)){ stop_net_queue(dev); }else{ ++card->wandev.stats.tx_packets;#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.tx_bytes += skb->len;#endif#ifdef LINUX_2_4 dev->trans_start = jiffies;#endif start_net_queue(dev); } if_send_crit_exit: if (!(err=is_queue_stopped(dev))){ wan_dev_kfree_skb(skb, FREE_WRITE); }else{ chdlc_priv_area->tick_counter = jiffies; chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME; } clear_bit(SEND_CRIT, (void*)&card->wandev.critical); if(card->hw.type != SDLA_S514){ s508_unlock(card,&smp_flags); } return err;}/*============================================================================ * Reply to UDP Management system. * Return length of reply. */static int reply_udp( unsigned char *data, unsigned int mbox_len ){ unsigned short len, udp_length, temp, ip_length; unsigned long ip_temp; int even_bound = 0; chdlc_udp_pkt_t *c_udp_pkt = (chdlc_udp_pkt_t *)data; /* Set length of packet */ len = sizeof(ip_pkt_t)+ sizeof(udp_pkt_t)+ sizeof(wp_mgmt_t)+ sizeof(cblock_t)+ sizeof(trace_info_t)+ mbox_len; /* fill in UDP reply */ c_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY; /* fill in UDP length */ udp_length = sizeof(udp_pkt_t)+ sizeof(wp_mgmt_t)+ sizeof(cblock_t)+ sizeof(trace_info_t)+ mbox_len; /* put it on an even boundary */ if ( udp_length & 0x0001 ) { udp_length += 1; len += 1; even_bound = 1; } temp = (udp_length<<8)|(udp_length>>8); c_udp_pkt->udp_pkt.udp_length = temp; /* swap UDP ports */ temp = c_udp_pkt->udp_pkt.udp_src_port; c_udp_pkt->udp_pkt.udp_src_port = c_udp_pkt->udp_pkt.udp_dst_port; c_udp_pkt->udp_pkt.udp_dst_port = temp; /* add UDP pseudo header */ temp = 0x1100; *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound)) = temp; temp = (udp_length<<8)|(udp_length>>8); *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound+2)) = temp; /* calculate UDP checksum */ c_udp_pkt->udp_pkt.udp_checksum = 0; c_udp_pkt->udp_pkt.udp_checksum = calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET); /* fill in IP length */ ip_length = len; temp = (ip_length<<8)|(ip_length>>8); c_udp_pkt->ip_pkt.total_length = temp; /* swap IP addresses */ ip_temp = c_udp_pkt->ip_pkt.ip_src_address; c_udp_pkt->ip_pkt.ip_src_address = c_udp_pkt->ip_pkt.ip_dst_address; c_udp_pkt->ip_pkt.ip_dst_address = ip_temp; /* fill in IP checksum */ c_udp_pkt->ip_pkt.hdr_checksum = 0; c_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t)); return len;} /* reply_udp */unsigned short calc_checksum (char *data, int len){ unsigned short temp; unsigned long sum=0; int i; for( i = 0; i <len; i+=2 ) { memcpy(&temp,&data[i],2); sum += (unsigned long)temp; } while (sum >> 16 ) { sum = (sum & 0xffffUL) + (sum >> 16); } temp = (unsigned short)sum; temp = ~temp; if( temp == 0 ) temp = 0xffff; return temp; }/*============================================================================ * Get ethernet-style interface statistics. * Return a pointer to struct enet_statistics. */#if defined(LINUX_2_1) || defined(LINUX_2_4)static struct net_device_stats* if_stats (netdevice_t* dev){ sdla_t *my_card; chdlc_private_area_t* chdlc_priv_area; /* Shutdown bug fix. In del_if() we kill * dev->priv pointer. This function, gets * called after del_if(), thus check * if pointer has been deleted */ if ((chdlc_priv_area=dev->priv) == NULL) return NULL; my_card = chdlc_priv_area->card; return &my_card->wandev.stats; }#elsestatic struct enet_statistics* if_stats (netdevice_t* dev){ sdla_t *my_card; chdlc_private_area_t* chdlc_priv_area = dev->priv; /* Shutdown bug fix. In del_if() we kill * dev->priv pointer. This function, gets * called after del_if(), thus check * if pointer has been deleted */ if ((chdlc_priv_area=dev->priv) == NULL) return NULL; my_card = chdlc_priv_area->card; return &my_card->wandev.stats;}#endif/****** Cisco HDLC Firmware Interface Functions *******************************//*============================================================================ * Read firmware code version. * Put code version as ASCII string in str. */static int chdlc_read_version (sdla_t* card, char* str){ CHDLC_MAILBOX_STRUCT* mb = card->mbox; int len; char err; mb->buffer_length = 0; mb->command = READ_CHDLC_CODE_VERSION; err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; if(err != COMMAND_OK) { chdlc_error(card,err,mb); } else if (str) { /* is not null */ len = mb->buffer_length; memcpy(str, mb->data, len); str[len] = '\0'; } return (err);}/*----------------------------------------------------------------------------- * Configure CHDLC firmware. */static int chdlc_configure (sdla_t* card, void* data){ int err; CHDLC_MAILBOX_STRUCT *mailbox = card->mbox; int data_length = sizeof(CHDLC_CONFIGURATION_STRUCT); mailbox->buffer_length = data_length; memcpy(mailbox->data, data, data_length); mailbox->command = SET_CHDLC_CONFIGURATION; err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT; if (err != COMMAND_OK) chdlc_error (card, err, mailbox); return err;}/*============================================================================ * Set interrupt mode -- HDLC Version. */static int chdlc_set_intr_mode (sdla_t* card, unsigned mode){ CHDLC_MAILBOX_STRUCT* mb = card->mbox; CHDLC_INT_TRIGGERS_STRUCT* int_data = (CHDLC_INT_TRIGGERS_STRUCT *)mb->data; int err; int_data->CHDLC_interrupt_triggers = mode; int_data->IRQ = card->hw.irq; int_data->interrupt_timer = 1; mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT); mb->command = SET_CHDLC_INTERRUPT_TRIGGERS; err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; if (err != COMMAND_OK) chdlc_error (card, err, mb); return err;}/*============================================================================ * Enable communications. */static int chdlc_comm_enable (sdla_t* card){ int err; CHDLC_MAILBOX_STRUCT* mb = card->mbox; mb->buffer_length = 0; mb->command = ENABLE_CHDLC_COMMUNICATIONS; err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; if (err != COMMAND_OK) chdlc_error(card, err, mb); else card->u.c.comm_enabled=1; return err;}/*============================================================================ * Disable communications and Drop the Modem lines (DCD and RTS). */static int chdlc_comm_disable (sdla_t* card){ int err; CHDLC_MAILBOX_STRUCT* mb = card->mbox; mb->buffer_length = 0; mb->command = DISABLE_CHDLC_COMMUNICATIONS; err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; if (err != COMMAND_OK) chdlc_error(card,err,mb); return err;}/*============================================================================ * Read communication error statistics. */static int chdlc_read_comm_err_stats (sdla_t* card){ int err; CHDLC_MAILBOX_STRUCT* mb = card->mbox; mb->buffer_length = 0; mb->command = READ_COMMS_ERROR_STATS; err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; if (err != COMMAND_OK) chdlc_error(card,err,mb); return err;}/*============================================================================ * Read CHDLC operational statistics. */static int chdlc_read_op_stats (sdla_t* card){ int err; CHDLC_MAILBOX_STRUCT* mb = card->mbox; mb->buffer_length = 0; mb->command = READ_CHDLC_OPERATIONAL_STATS; err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; if (err != COMMAND_OK) chdlc_error(card,err,mb); return err;}/*============================================================================ * Update communications error and general packet statistics. */static int update_comms_stats(sdla_t* card, chdlc_private_area_t* chdlc_priv_area){ CHDLC_MAILBOX_STRUCT* mb = card->mbox; COMMS_ERROR_STATS_STRUCT* err_stats; CHDLC_OPERATIONAL_STATS_STRUCT *op_stats; /* on the first timer interrupt, read the comms error statistics */ if(chdlc_priv_area->update_comms_stats == 2) { if(chdlc_read_comm_err_stats(card)) return 1; err_stats = (COMMS_ERROR_STATS_STRUCT *)mb->data; card->wandev.stats.rx_over_errors = err_stats->Rx_overrun_err_count; card->wandev.stats.rx_crc_errors = err_stats->CRC_err_count; card->wandev.stats.rx_frame_errors = err_stats->Rx_abort_count; card->wandev.stats.rx_fifo_errors = err_stats->Rx_dis_pri_bfrs_full_count; card->wandev.stats.rx_missed_errors = card->wandev.stats.rx_fifo_errors; card->wandev.stats.tx_aborted_errors = err_stats->sec_Tx_abort_count; } /* on the second timer interrupt, read the operational statistics */ else { if(chdlc_read_op_stats(card)) return 1; op_stats = (CHDLC_OPERATIONAL_STATS_STRUCT *)mb->data; card->wandev.stats.rx_length_errors = (op_stats->Rx_Data_discard_short_count + op_stats->Rx_Data_discard_long_count); } return 0;}/*============================================================================ * Send packet. * Return: 0 - o.k. * 1 - no transmit buffers available */static int chdlc_send (sdla_t* card, void* data, unsigned len){ CHDLC_DATA_TX_STATUS_EL_STRUCT *txbuf = card->u.c.txbuf; if (txbuf->opp_flag) return 1; sdla_poke(&card->hw, txbuf->ptr_data_bfr, data, len); txbuf->frame_length = len; txbuf->opp_flag = 1; /* start transmission */ /* Update transmit buffer control fields */ card->u.c.txbuf = ++txbuf; if ((void*)txbuf > card->u.c.txbuf_last) card->u.c.txbuf = card->u.c.txbuf_base; return 0;}/****** Firmware Error Handler **********************************************//*============================================================================ * Firmware error handler. * This routine is called whenever firmware command returns non-zero * return code. * * Return zero if previous command has to be cancelled. */static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb){ unsigned cmd = mb->command; switch (err) { case CMD_TIMEOUT: printk(KERN_ERR "%s: command 0x%02X timed out!\n", card->devname, cmd); break; case S514_BOTH_PORTS_SAME_CLK_MODE: if(cmd == SET_CHDLC_CONFIGURATION) { printk(KERN_INFO "%s: Configure both ports for the same clock source\n", card->devname); break; } default: printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n", card->devname, cmd, err); } return 0;}/****** Interrupt Handlers **************************************************//*============================================================================ * Cisco HDLC interrupt service routine. */STATIC void wsppp_isr (sdla_t* card){ netdevice_t* dev; SHARED_MEMORY_INFO_STRUCT* flags = NULL; int i; sdla_t *my_card; /* Check for which port the interrupt has been generated * Since Secondary Port is piggybacking on the Primary * the check must be done here. */ flags = card->u.c.flags; if (!flags->interrupt_info_struct.interrupt_type){ /* Check for a second port (piggybacking) */ if((my_card = card->next)){ flags = my_card->u.c.flags; if (flags->interrupt_info_struct.interrupt_type){ card = my_card; card->isr(card); return; } } } dev = card->wandev.dev; card->in_isr = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -