📄 sdla_ppp.c
字号:
ppp_error(card, err, mb); 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); return err;}/*============================================================================ * 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; //FIXME: Do we need this card->force_enable_irq = 0; if(card->hw.type != SDLA_S514){ if (test_and_set_bit(0, (void*)&card->wandev.critical)) { ++card->statistics.isr_already_critical; printk (KERN_INFO "%s: Critical while in ISR!\n", card->devname); card->in_isr = 0; return; } } card->buff_int_mode_unbusy = 0; 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); card->buff_int_mode_unbusy = 1; 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; card->wandev.critical = 0; if(card->buff_int_mode_unbusy) netif_wake_queue(dev);}/*============================================================================ * 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; return; } if (dev && netif_running(dev)) { 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) { ppp_send(card, skb->data, skb->len, htons(ETH_P_IPX)); dev_kfree_skb(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); } } else { printk(KERN_INFO "%s: no socket buffers available!\n", card->devname); ++card->wandev.stats.rx_dropped; ++ppp_priv_area->rx_intr_stat.rx_intr_no_socket; dev_kfree_skb(skb); } } else { ++card->statistics.rx_intr_dev_not_started; } /* Release buffer element and calculate a pointer to the next one */ rxbuf->flag = 0x00; card->rxmb = ++rxbuf; if ((void*)rxbuf > card->u.p.rxbuf_last) card->rxmb = card->u.p.rxbuf_base;}void event_intr (sdla_t *card){ struct net_device* dev = card->wandev.dev; ppp_private_area_t* ppp_priv_area = dev->priv; volatile ppp_flags_t *flags = card->flags; switch (flags->iflag){ case PPP_INTR_MODEM: /* modem status change (DCD, CTS) 0x04 (bit 2)*/ printk (KERN_INFO "%s: Modem status: DCD=%s CTS=%s\n", card->devname, DCD(flags->mstatus), CTS(flags->mstatus)); break; case PPP_INTR_DISC: /* Data link disconnected 0x10 (bit 4)*/ NEX_PRINTK (KERN_INFO "Data link disconnected intr Cause %X\n", flags->disc_cause); if (flags->disc_cause & (PPP_LOCAL_TERMINATION | PPP_DCD_CTS_DROP | PPP_REMOTE_TERMINATION)) { if (card->u.p.ip_mode == WANOPT_PPP_PEER) { Read_connection_info = 1; remove_route (card); } wanpipe_set_state(card, WAN_DISCONNECTED); show_disc_cause(card, flags->disc_cause); ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT; flags->imask |= PPP_INTR_TIMER; } break; case PPP_INTR_OPEN: /* Data link open 0x20 (bit 5)*/ NEX_PRINTK (KERN_INFO "%s: PPP Link Open, LCP=%s IP=%s\n", card->devname,LCP(flags->lcp_state), IP(flags->ip_state)); if (flags->lcp_state == 0x09 && (flags->ip_state == 0x09 || flags->ipx_state == 0x09)){ /* Initialize the polling timer and set the state * to WAN_CONNNECTED */ card->state_tick = jiffies; wanpipe_set_state(card, WAN_CONNECTED); ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT; flags->imask |= PPP_INTR_TIMER; } break; case PPP_INTR_DROP_DTR: /* DTR drop timeout expired 0x40 bit 6 */ NEX_PRINTK(KERN_INFO "DTR Drop Timeout Interrrupt \n"); if (card->u.p.ip_mode == WANOPT_PPP_PEER) { Read_connection_info = 1; remove_route (card); } wanpipe_set_state(card, WAN_DISCONNECTED); show_disc_cause(card, flags->disc_cause); ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT; flags->imask |= PPP_INTR_TIMER; break; default: printk(KERN_INFO "%s: Error, Invalid PPP Event\n",card->devname); }}/* TIMER INTERRUPT */void timer_intr (sdla_t *card){ struct net_device* dev = card->wandev.dev; ppp_private_area_t* ppp_priv_area = dev->priv; ppp_flags_t *flags = card->flags; /* Update statistics */ if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE){ ppp_get_err_stats(card); if(!(--ppp_priv_area->update_comms_stats)){ ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE; } } /* PPIPEMON UDP request */ if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP){ process_udp_mgmt_pkt(card,dev, ppp_priv_area); ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP; } /* PPP Event */ if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_PPP_EVENT){ if (card->wandev.state == WAN_DISCONNECTED){ poll_disconnected(card); } /* If the state is CONNECTING, it means that communicatins were * enabled. When the remote side enables its comminication we * should get an interrupt PPP_INTR_OPEN, thus turn off polling */ else if (card->wandev.state == WAN_CONNECTING){ /* Turn off the timer interrupt */ ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_PPP_EVENT; } /* If state is connected and we are in PEER mode * poll for an IP address which will be provided by remote end. */ else if ((card->wandev.state == WAN_CONNECTED && card->u.p.ip_mode == WANOPT_PPP_PEER) && Read_connection_info){ card->state_tick = jiffies; if (!read_connection_info (card)){ card->poll = &process_route; } }else{ /* If we are using Static IP,no need to poll for * an IP address. */ NEX_PRINTK(KERN_INFO "Turning off TIMER \n"); ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_PPP_EVENT; } }/* End of PPP_EVENT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -