📄 sdla_ppp.c
字号:
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 && is_dev_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)); } wan_dev_kfree_skb(skb,FREE_READ); } 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;#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.rx_bytes += skb->len;#endif ++ppp_priv_area->rx_intr_stat.rx_intr_bfr_passed_to_stack; netif_rx(skb); } } else { if (net_ratelimit()){ 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; } } 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){ netdevice_t* 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)*/ if (net_ratelimit()){ 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) { set_bit(0,&Read_connection_info); } 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; trigger_ppp_poll(dev); } 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 */ /* BUG FIX: When the protocol restarts, during heavy * traffic, board tx buffers and driver tx buffers * can go out of sync. This checks the condition * and if the tx buffers are out of sync, the * protocols are restarted. * I don't know why the board tx buffer is out * of sync. It could be that a packets is tx * while the link is down, but that is not * possible. The other possiblility is that the * firmware doesn't reinitialize properly. * FIXME: A better fix should be found. */ if (detect_and_fix_tx_bug(card)){ ppp_comm_disable(card); wanpipe_set_state(card, WAN_DISCONNECTED); ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT; flags->imask |= PPP_INTR_TIMER; break; } card->state_tick = jiffies; wanpipe_set_state(card, WAN_CONNECTED); NEX_PRINTK(KERN_INFO "CON: L Tx: %lx B Tx: %lx || L Rx %lx B Rx %lx\n", (unsigned long)card->u.p.txbuf, *card->u.p.txbuf_next, (unsigned long)card->rxmb, *card->u.p.rxbuf_next); /* Tell timer interrupt that PPP event occured */ ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT; flags->imask |= PPP_INTR_TIMER; /* If we are in PEER mode, we must first obtain the * IP information and then go into the poll routine */ if (card->u.p.ip_mode != WANOPT_PPP_PEER){ trigger_ppp_poll(dev); } } 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) { set_bit(0,&Read_connection_info); } 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; trigger_ppp_poll(dev); break; default: printk(KERN_INFO "%s: Error, Invalid PPP Event\n",card->devname); }}/* TIMER INTERRUPT */void timer_intr (sdla_t *card){ netdevice_t* dev = card->wandev.dev; ppp_private_area_t* ppp_priv_area = dev->priv; ppp_flags_t *flags = card->flags; if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG){ if (!config_ppp(card)){ ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG; } } /* 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){ retrigger_comm(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) && test_bit(0,&Read_connection_info)){ card->state_tick = jiffies; if (read_connection_info (card)){ printk(KERN_INFO "%s: Failed to read PEER IP Addresses\n", card->devname); }else{ clear_bit(0,&Read_connection_info); set_bit(1,&Read_connection_info); trigger_ppp_poll(dev); } }else{ //FIXME Put the comment back int ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_PPP_EVENT; } }/* End of PPP_EVENT */ /* Only disable the timer interrupt if there are no udp, statistic */ /* updates or events pending */ if(!ppp_priv_area->timer_int_enabled) { flags->imask &= ~PPP_INTR_TIMER; }}static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto){ int i; if( proto == htons(ETH_P_IPX) ) { //It's an IPX packet if(!enable_IPX) { //Return 1 so we don't pass it up the stack. return 1; } } else { //It's not IPX so pass it up the stack. return 0; } if( sendpacket[16] == 0x90 && sendpacket[17] == 0x04) { //It's IPXWAN if( sendpacket[2] == 0x02 && sendpacket[34] == 0x00) { //It's a timer request packet printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",devname); //Go through the routing options and answer no to every //option except Unnumbered RIP/SAP for(i = 41; sendpacket[i] == 0x00; i += 5) { //0x02 is the option for Unnumbered RIP/SAP if( sendpacket[i + 4] != 0x02) { sendpacket[i + 1] = 0; } } //Skip over the extended Node ID option if( sendpacket[i] == 0x04 ) { i += 8; } //We also want to turn off all header compression opt. for(; sendpacket[i] == 0x80 ;) { sendpacket[i + 1] = 0; i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4; } //Set the packet type to timer response sendpacket[34] = 0x01; printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",devname); } else if( sendpacket[34] == 0x02 ) { //This is an information request packet printk(KERN_INFO "%s: Received IPXWAN Information Request packet\n",devname); //Set the packet type to information response sendpacket[34] = 0x03; //Set the router name sendpacket[51] = 'P'; sendpacket[52] = 'T'; sendpacket[53] = 'P'; sendpacket[54] = 'I'; sendpacket[55] = 'P'; sendpacket[56] = 'E'; sendpacket[57] = '-'; sendpacket[58] = CVHexToAscii(network_number >> 28); sendpacket[59] = CVHexToAscii((network_number & 0x0F000000)>> 24); sendpacket[60] = CVHexToAscii((network_number & 0x00F00000)>> 20); sendpacket[61] = CVHexToAscii((network_number & 0x000F0000)>> 16); sendpacket[62] = CVHexToAscii((network_number & 0x0000F000)>> 12); sendpacket[63] = CVHexToAscii((network_number & 0x00000F00)>> 8); sendpacket[64] = CVHexToAscii((network_number & 0x000000F0)>> 4); sendpacket[65] = CVHexToAscii(network_number & 0x0000000F); for(i = 66; i < 99; i+= 1) { sendpacket[i] = 0; } printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",devname); } else { printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname); return 0; } //Set the WNodeID to our network address sendpacket[35] = (unsigned char)(network_number >> 24); sendpacket[36] = (unsigned char)((network_number & 0x00FF0000) >> 16); sendpacket[37] = (unsigned char)((network_number & 0x0000FF00) >> 8); sendpacket[38] = (unsigned char)(network_number & 0x000000FF); return 1; } else { //If we get here's its an IPX-data packet, so it'll get passed up the stack. //switch the network numbers switch_net_numbers(sendpacket, network_number, 1); return 0; }}/****** Background Polling Routines ****************************************//* All polling functions are invoked by the TIMER interrupt in the wpp_isr * routine. *//*============================================================================ * Monitor active link phase. */static void process_route (sdla_t *card){ ppp_flags_t *flags = card->flags; netdevice_t *dev = card->wandev.dev; ppp_private_area_t *ppp_priv_area = dev->priv; #if defined(LINUX_2_1) || defined(LINUX_2_4) if ((card->u.p
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -