📄 sdla_ppp.c
字号:
tokens[0] = strsep(&str, "/"); while (tokens[cnt] && (cnt < 32 - 1)) { tokens[cnt] = strstrip(tokens[cnt], " \t"); tokens[++cnt] = strsep(&str, "/"); } return cnt;}/*============================================================================ * Strip leading and trailing spaces off the string str. */static char* strstrip (char *str, char* s){ char *eos = str + strlen(str); /* -> end of string */ while (*str && strchr(s, *str)) ++str /* strip leading spaces */ ; while ((eos > str) && strchr(s, *(eos - 1))) --eos /* strip trailing spaces */ ; *eos = '\0'; return str;}/*============================================================================ * Configure PPP firmware. */static int ppp_configure(sdla_t *card, void *data){ ppp_mbox_t *mb = card->mbox; int data_len = sizeof(ppp508_conf_t); int err; memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); memcpy(mb->data, data, data_len); mb->cmd.length = data_len; mb->cmd.command = PPP_SET_CONFIG; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; if (err != CMD_OK) ppp_error(card, err, mb); return err;}/*============================================================================ * Set interrupt mode. */static int ppp_set_intr_mode(sdla_t *card, unsigned char mode){ ppp_mbox_t *mb = card->mbox; ppp_intr_info_t *ppp_intr_data = (ppp_intr_info_t *) &mb->data[0]; int err; memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); ppp_intr_data->i_enable = mode; ppp_intr_data->irq = card->hw.irq; mb->cmd.length = 2; /* If timer has been enabled, set the timer delay to 1sec */ if (mode & 0x80){ ppp_intr_data->timer_len = 250; //5;//100; //250; mb->cmd.length = 4; } mb->cmd.command = PPP_SET_INTR_FLAGS; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; if (err != CMD_OK) ppp_error(card, err, mb); return err;}/*============================================================================ * Enable communications. */static int ppp_comm_enable(sdla_t *card){ ppp_mbox_t *mb = card->mbox; int err; memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); mb->cmd.command = PPP_COMM_ENABLE; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; if (err != CMD_OK) ppp_error(card, err, mb); else card->u.p.comm_enabled = 1; return err;}/*============================================================================ * Disable communications. */static int ppp_comm_disable(sdla_t *card){ ppp_mbox_t *mb = card->mbox; int err; memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); mb->cmd.command = PPP_COMM_DISABLE; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; if (err != CMD_OK) ppp_error(card, err, mb); else card->u.p.comm_enabled = 0; return err;}static int ppp_comm_disable_shutdown(sdla_t *card){ ppp_mbox_t *mb = card->mbox; ppp_intr_info_t *ppp_intr_data; int err; if (!mb){ return 1; } ppp_intr_data = (ppp_intr_info_t *) &mb->data[0]; /* Disable all interrupts */ memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); ppp_intr_data->i_enable = 0; ppp_intr_data->irq = card->hw.irq; mb->cmd.length = 2; mb->cmd.command = PPP_SET_INTR_FLAGS; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; /* Disable communicatinons */ memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); mb->cmd.command = PPP_COMM_DISABLE; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; card->u.p.comm_enabled = 0; return 0;}/*============================================================================ * Get communications error statistics. */static int ppp_get_err_stats(sdla_t *card){ ppp_mbox_t *mb = card->mbox; int err; memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); mb->cmd.command = PPP_READ_ERROR_STATS; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; if (err == CMD_OK) { ppp_err_stats_t* stats = (void*)mb->data; card->wandev.stats.rx_over_errors = stats->rx_overrun; card->wandev.stats.rx_crc_errors = stats->rx_bad_crc; card->wandev.stats.rx_missed_errors = stats->rx_abort; card->wandev.stats.rx_length_errors = stats->rx_lost; card->wandev.stats.tx_aborted_errors = stats->tx_abort; } else ppp_error(card, err, mb); return err;}/*============================================================================ * Send packet. * Return: 0 - o.k. * 1 - no transmit buffers available */static int ppp_send (sdla_t *card, void *data, unsigned len, unsigned proto){ ppp_buf_ctl_t *txbuf = card->u.p.txbuf; if (txbuf->flag) return 1; sdla_poke(&card->hw, txbuf->buf.ptr, data, len); txbuf->length = len; /* frame length */ if (proto == htons(ETH_P_IPX)) txbuf->proto = 0x01; /* protocol ID */ else txbuf->proto = 0x00; /* protocol ID */ txbuf->flag = 1; /* start transmission */ /* Update transmit buffer control fields */ card->u.p.txbuf = ++txbuf; if ((void*)txbuf > card->u.p.txbuf_last) card->u.p.txbuf = card->u.p.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 ppp_error(sdla_t *card, int err, ppp_mbox_t *mb){ unsigned cmd = mb->cmd.command; switch (err) { case CMD_TIMEOUT: printk(KERN_ERR "%s: command 0x%02X timed out!\n", card->devname, cmd); break; default: printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n" , card->devname, cmd, err); } return 0;}/****** Interrupt Handlers **************************************************//*============================================================================ * PPP interrupt service routine. */static void wpp_isr (sdla_t *card){ ppp_flags_t *flags = card->flags; char *ptr = &flags->iflag; struct net_device *dev = card->wandev.dev; int i; card->in_isr = 1; ++card->statistics.isr_entry; if (!dev && flags->iflag != PPP_INTR_CMD){ card->in_isr = 0; flags->iflag = 0; return; } if (test_bit(PERI_CRIT, (void*)&card->wandev.critical)) { card->in_isr = 0; flags->iflag = 0; return; } if(card->hw.type != SDLA_S514){ if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)) { ++card->statistics.isr_already_critical; printk (KERN_INFO "%s: Critical while in ISR!\n", card->devname); card->in_isr = 0; flags->iflag = 0; return; } } switch (flags->iflag) { case PPP_INTR_RXRDY: /* receive interrupt 0x01 (bit 0)*/ ++card->statistics.isr_rx; rx_intr(card); break; case PPP_INTR_TXRDY: /* transmit interrupt 0x02 (bit 1)*/ ++card->statistics.isr_tx; flags->imask &= ~PPP_INTR_TXRDY; netif_wake_queue(dev); break; case PPP_INTR_CMD: /* interface command completed */ ++Intr_test_counter; ++card->statistics.isr_intr_test; break; case PPP_INTR_MODEM: /* modem status change (DCD, CTS) 0x04 (bit 2)*/ case PPP_INTR_DISC: /* Data link disconnected 0x10 (bit 4)*/ case PPP_INTR_OPEN: /* Data link open 0x20 (bit 5)*/ case PPP_INTR_DROP_DTR: /* DTR drop timeout expired 0x40 bit 6 */ event_intr(card); break; case PPP_INTR_TIMER: timer_intr(card); break; default: /* unexpected interrupt */ ++card->statistics.isr_spurious; printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n", card->devname, flags->iflag); printk(KERN_INFO "%s: ID Bytes = ",card->devname); for(i = 0; i < 8; i ++) printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i)); printk(KERN_INFO "\n"); } card->in_isr = 0; flags->iflag = 0; return;}/*============================================================================ * Receive interrupt handler. */static void rx_intr(sdla_t *card){ ppp_buf_ctl_t *rxbuf = card->rxmb; struct net_device *dev = card->wandev.dev; ppp_private_area_t *ppp_priv_area; struct sk_buff *skb; unsigned len; void *buf; int i; ppp_flags_t *flags = card->flags; char *ptr = &flags->iflag; int udp_type; if (rxbuf->flag != 0x01) { printk(KERN_INFO "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", card->devname, (unsigned)rxbuf, rxbuf->flag); printk(KERN_INFO "%s: ID Bytes = ",card->devname); for(i = 0; i < 8; i ++) printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i)); printk(KERN_INFO "\n"); ++card->statistics.rx_intr_corrupt_rx_bfr; /* Bug Fix: Mar 6 2000 * If we get a corrupted mailbox, it means 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"); ppp_set_intr_mode(card,0); return; } if (dev && netif_running(dev) && dev->priv){ len = rxbuf->length; ppp_priv_area = dev->priv; /* Allocate socket buffer */ skb = dev_alloc_skb(len); if (skb != NULL) { /* Copy data to the socket buffer */ unsigned addr = rxbuf->buf.ptr; if ((addr + len) > card->u.p.rx_top + 1) { unsigned tmp = card->u.p.rx_top - addr + 1; buf = skb_put(skb, tmp); sdla_peek(&card->hw, addr, buf, tmp); addr = card->u.p.rx_base; len -= tmp; } buf = skb_put(skb, len); sdla_peek(&card->hw, addr, buf, len); /* Decapsulate packet */ switch (rxbuf->proto) { case 0x00: skb->protocol = htons(ETH_P_IP); break; case 0x01: skb->protocol = htons(ETH_P_IPX); break; } udp_type = udp_pkt_type( skb, card ); if (udp_type == UDP_PTPIPE_TYPE){ /* Handle a UDP Request in Timer Interrupt */ if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK, card, skb, dev, ppp_priv_area)){ flags->imask |= PPP_INTR_TIMER; } ++ppp_priv_area->rx_intr_stat.rx_intr_PIPE_request; } else if (handle_IPXWAN(skb->data,card->devname, ppp_priv_area->enable_IPX, ppp_priv_area->network_number, skb->protocol)) { /* Handle an IPXWAN packet */ if( ppp_priv_area->enable_IPX) { /* Make sure we are not already sending */ if (!test_bit(SEND_CRIT, &card->wandev.critical)){ ppp_send(card, skb->data, skb->len, htons(ETH_P_IPX)); } dev_kfree_skb_any(skb); } else { ++card->wandev.stats.rx_dropped; } } else { /* Pass data up the protocol stack */ skb->dev = dev; skb->mac.raw = skb->data; ++card->wandev.stats.rx_packets; card->wandev.stats.rx_bytes += skb->len; ++ppp_priv_area->rx_intr_stat.rx_intr_bfr_passed_to_stack; netif_rx(skb); dev->last_rx = jiffies; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -