📄 wanpipe_multppp.c
字号:
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. */static struct net_device_stats* if_stats(struct net_device* 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; }/****** 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){ struct net_device* 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; flags = card->u.c.flags; /* If we get an interrupt with no network device, stop the interrupts * and issue an error */ if ((!dev || !dev->priv) && flags->interrupt_info_struct.interrupt_type != COMMAND_COMPLETE_APP_INT_PEND){ goto isr_done; } /* if critical due to peripheral operations * ie. update() or getstats() then reset the interrupt and * wait for the board to retrigger. */ if(test_bit(PERI_CRIT, (void*)&card->wandev.critical)) { flags->interrupt_info_struct. interrupt_type = 0; goto isr_done; } /* On a 508 Card, if critical due to if_send * Major Error !!! */ if(card->hw.type != SDLA_S514) { if(test_bit(0, (void*)&card->wandev.critical)) { printk(KERN_INFO "%s: Critical while in ISR: %lx\n", card->devname, card->wandev.critical); goto isr_done; } } switch(flags->interrupt_info_struct.interrupt_type) { case RX_APP_INT_PEND: /* 0x01: receive interrupt */ rx_intr(card); break; case TX_APP_INT_PEND: /* 0x02: transmit interrupt */ flags->interrupt_info_struct.interrupt_permission &= ~APP_INT_ON_TX_FRAME; netif_wake_queue(dev); break; case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */ ++ Intr_test_counter; break; case CHDLC_EXCEP_COND_APP_INT_PEND: /* 0x20 */ process_chdlc_exception(card); break; case GLOBAL_EXCEP_COND_APP_INT_PEND: process_global_exception(card); break; case TIMER_APP_INT_PEND: timer_intr(card); break; default: printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n", card->devname, flags->interrupt_info_struct.interrupt_type); 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"); break; }isr_done: card->in_isr = 0; flags->interrupt_info_struct.interrupt_type = 0;}/*============================================================================ * Receive interrupt handler. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -