📄 sdla_chdlc.c
字号:
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; 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;}/*=========================================================== * chdlc_disable_comm_shutdown * * Shutdown() disables the communications. We must * have a sparate functions, because we must not * call chdlc_error() hander since the private * area has already been replaced */static int chdlc_disable_comm_shutdown (sdla_t *card){ CHDLC_MAILBOX_STRUCT* mb = card->mbox; CHDLC_INT_TRIGGERS_STRUCT* int_data = (CHDLC_INT_TRIGGERS_STRUCT *)mb->data; int err; /* Disable Interrutps */ int_data->CHDLC_interrupt_triggers = 0; 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; /* Disable Communications */ if (card->u.c.async_mode) { mb->command = DISABLE_ASY_COMMUNICATIONS; }else{ mb->command = DISABLE_CHDLC_COMMUNICATIONS; } mb->buffer_length = 0; err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; card->u.c.comm_enabled = 0; return 0;}/*============================================================================ * 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;}/*============================================================================ * 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_INFO "%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;}/********** Bottom Half Handlers ********************************************//* NOTE: There is no API, BH support for Kernels lower than 2.2.X. * DO NOT INSERT ANY CODE HERE, NOTICE THE * PREPROCESSOR STATEMENT ABOVE, UNLESS YOU KNOW WHAT YOU ARE * DOING */static void chdlc_work(struct net_device * dev){ chdlc_private_area_t* chan = dev->priv; sdla_t *card = chan->card; struct sk_buff *skb; if (atomic_read(&chan->bh_buff_used) == 0){ clear_bit(0, &chan->tq_working); return; } while (atomic_read(&chan->bh_buff_used)){ skb = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb; if (skb != NULL){ if (chan->common.sk == NULL || chan->common.func == NULL){ ++card->wandev.stats.rx_dropped; dev_kfree_skb_any(skb); chdlc_work_cleanup(dev); continue; } if (chan->common.func(skb,dev,chan->common.sk) != 0){ /* Sock full cannot send, queue us for another * try */ atomic_set(&chan->common.receive_block,1); return; }else{ chdlc_work_cleanup(dev); } }else{ chdlc_work_cleanup(dev); } } clear_bit(0, &chan->tq_working); return;}static int chdlc_work_cleanup(struct net_device *dev){ chdlc_private_area_t* chan = dev->priv; ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL; if (chan->bh_read == MAX_BH_BUFF){ chan->bh_read=0; }else{ ++chan->bh_read; } atomic_dec(&chan->bh_buff_used); return 0;}static int bh_enqueue(struct net_device *dev, struct sk_buff *skb){ /* Check for full */ chdlc_private_area_t* chan = dev->priv; sdla_t *card = chan->card; if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){ ++card->wandev.stats.rx_dropped; dev_kfree_skb_any(skb); return 1; } ((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb; if (chan->bh_write == MAX_BH_BUFF){ chan->bh_write=0; }else{ ++chan->bh_write; } atomic_inc(&chan->bh_buff_used); return 0;}/* END OF API BH Support *//****** Interrupt Handlers **************************************************//*============================================================================ * Cisco HDLC interrupt service routine. */static void wpc_isr (sdla_t* card){ struct net_device* dev; SHARED_MEMORY_INFO_STRUCT* flags = NULL; int i; sdla_t *my_card;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -