⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wanpipe_multppp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
 *      3) CHDLC operational statistics on the adapter. * The board level statistics are read during a timer interrupt. Note that we  * read the error and operational statistics during consecitive timer ticks so * as to minimize the time that we are inside the interrupt handler. * */static int update(struct wan_device* wandev){	sdla_t* card = wandev->private; 	struct net_device* dev;        volatile chdlc_private_area_t* chdlc_priv_area;        SHARED_MEMORY_INFO_STRUCT *flags;	unsigned long timeout;	/* sanity checks */	if((wandev == NULL) || (wandev->private == NULL))		return -EFAULT;		if(wandev->state == WAN_UNCONFIGURED)		return -ENODEV;	/* more sanity checks */        if(!card->u.c.flags)                return -ENODEV;	if((dev=card->wandev.dev) == NULL)		return -ENODEV;	if((chdlc_priv_area=dev->priv) == NULL)		return -ENODEV;      	flags = card->u.c.flags;       	if(chdlc_priv_area->update_comms_stats){		return -EAGAIN;	}				/* we will need 2 timer interrupts to complete the */	/* reading of the statistics */	chdlc_priv_area->update_comms_stats = 2;       	flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;	chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UPDATE;  	/* wait a maximum of 1 second for the statistics to be updated */         timeout = jiffies + 1 * HZ;        for(;;) {		if(chdlc_priv_area->update_comms_stats == 0)			break;                if (time_after(jiffies, timeout)){    			chdlc_priv_area->update_comms_stats = 0; 			chdlc_priv_area->timer_int_enabled &=				~TMR_INT_ENABLED_UPDATE;  			return -EAGAIN;		}        }	return 0;}/*============================================================================ * Create new logical channel. * This routine is called by the router when ROUTER_IFNEW IOCTL is being * handled. * o parse media- and hardware-specific configuration * o make sure that a new channel can be created * o allocate resources, if necessary * o prepare network device structure for registaration. * * Return:	0	o.k. *		< 0	failure (channel will not be created) */static int new_if(struct wan_device* wandev, struct net_device* pdev,		  wanif_conf_t* conf){	struct ppp_device *pppdev = (struct ppp_device *)pdev;	struct net_device *dev = NULL;	struct sppp *sp;	sdla_t* card = wandev->private;	chdlc_private_area_t* chdlc_priv_area;		if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) {		printk(KERN_INFO "%s: invalid interface name!\n",			card->devname);		return -EINVAL;	}			/* allocate and initialize private data */	chdlc_priv_area = kmalloc(sizeof(chdlc_private_area_t), GFP_KERNEL);		if(chdlc_priv_area == NULL) 		return -ENOMEM;	memset(chdlc_priv_area, 0, sizeof(chdlc_private_area_t));	chdlc_priv_area->card = card; 	/* initialize data */	strcpy(card->u.c.if_name, conf->name);	if(card->wandev.new_if_cnt > 0) {                kfree(chdlc_priv_area);		return -EEXIST;	}	card->wandev.new_if_cnt++;	chdlc_priv_area->TracingEnabled = 0;	//We don't need this any more	chdlc_priv_area->route_status = NO_ROUTE;	chdlc_priv_area->route_removed = 0;	printk(KERN_INFO "%s: Firmware running in HDLC STREAMING Mode\n",		wandev->name);		/* Setup wanpipe as a router (WANPIPE) or as an API */	if( strcmp(conf->usedby, "WANPIPE") == 0) {		printk(KERN_INFO "%s: Driver running in WANPIPE mode!\n",			wandev->name);		card->u.c.usedby = WANPIPE;	} else {		printk(KERN_INFO 			"%s: API Mode is not supported for SyncPPP!\n",			wandev->name);		kfree(chdlc_priv_area);		return -EINVAL;	}	/* Get Multicast Information */	chdlc_priv_area->mc = conf->mc;	chdlc_priv_area->if_ptr = pppdev;	/* prepare network device data space for registration */	strcpy(dev->name,card->u.c.if_name);	/* Attach PPP protocol layer to pppdev	 * The sppp_attach() will initilize the dev structure         * and setup ppp layer protocols.         * All we have to do is to bind in:         *        if_open(), if_close(), if_send() and get_stats() functions.         */	sppp_attach(pppdev);	dev = pppdev->dev;	sp = &pppdev->sppp;		/* Enable PPP Debugging */	// FIXME Fix this up somehow	//sp->pp_flags |= PP_DEBUG; 		sp->pp_flags &= ~PP_CISCO;	dev->init = &if_init;	dev->priv = chdlc_priv_area;		return 0;}/*============================================================================ * Delete logical channel. */static int del_if(struct wan_device* wandev, struct net_device* dev){	chdlc_private_area_t *chdlc_priv_area = dev->priv;	sdla_t *card = chdlc_priv_area->card;	unsigned long smp_lock;		/* Detach the PPP layer */	printk(KERN_INFO "%s: Detaching SyncPPP Module from %s\n",			wandev->name,dev->name);	lock_adapter_irq(&wandev->lock,&smp_lock);	sppp_detach(dev);	chdlc_priv_area->if_ptr=NULL;		chdlc_set_intr_mode(card, 0);	if (card->u.c.comm_enabled)		chdlc_comm_disable(card);	unlock_adapter_irq(&wandev->lock,&smp_lock);		port_set_state(card, WAN_DISCONNECTED);	return 0;}/****** Network Device Interface ********************************************//*============================================================================ * Initialize Linux network interface. * * This routine is called only once for each interface, during Linux network * interface registration.  Returning anything but zero will fail interface * registration. */static int if_init(struct net_device* dev){	chdlc_private_area_t* chdlc_priv_area = dev->priv;	sdla_t* card = chdlc_priv_area->card;	struct wan_device* wandev = &card->wandev;		/* NOTE: Most of the dev initialization was         *       done in sppp_attach(), called by new_if()          *       function. All we have to do here is         *       to link four major routines below.          */	/* Initialize device driver entry points */	dev->open		= &if_open;	dev->stop		= &if_close;	dev->hard_start_xmit	= &if_send;	dev->get_stats		= &if_stats;	dev->tx_timeout		= &if_tx_timeout;	dev->watchdog_timeo	= TX_TIMEOUT;	/* Initialize hardware parameters */	dev->irq	= wandev->irq;	dev->dma	= wandev->dma;	dev->base_addr	= wandev->ioport;	dev->mem_start	= wandev->maddr;	dev->mem_end	= wandev->maddr + wandev->msize - 1;	/* Set transmit buffer queue length          * If we over fill this queue the packets will         * be droped by the kernel.         * sppp_attach() sets this to 10, but         * 100 will give us more room at low speeds.	 */        dev->tx_queue_len = 100;   	return 0;}/*============================================================================ * Handle transmit timeout event from netif watchdog */static void if_tx_timeout(struct net_device *dev){    	chdlc_private_area_t* chan = dev->priv;	sdla_t *card = chan->card;		/* If our device stays busy for at least 5 seconds then we will	 * kick start the device by making dev->tbusy = 0.  We expect	 * that our device never stays busy more than 5 seconds. So this                 	 * is only used as a last resort.	 */	++card->wandev.stats.collisions;	printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);	netif_wake_queue (dev);}/*============================================================================ * Open network interface. * o enable communications and interrupts. * o prevent module from unloading by incrementing use count * * Return 0 if O.k. or errno. */static int if_open(struct net_device* dev){	chdlc_private_area_t* chdlc_priv_area = dev->priv;	sdla_t* card = chdlc_priv_area->card;	struct timeval tv;	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;	/* Only one open per interface is allowed */	if (netif_running(dev))		return -EBUSY;	/* Start PPP Layer */	if (sppp_open(dev)){		return -EIO;	}	do_gettimeofday(&tv);	chdlc_priv_area->router_start_time = tv.tv_sec; 	netif_start_queue(dev);		wanpipe_open(card);	chdlc_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG;	flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;	return 0;}/*============================================================================ * Close network interface. * o if this is the last close, then disable communications and interrupts. * o reset flags. */static int if_close(struct net_device* dev){	chdlc_private_area_t* chdlc_priv_area = dev->priv;	sdla_t* card = chdlc_priv_area->card;	/* Stop the PPP Layer */	sppp_close(dev);	netif_stop_queue(dev);	wanpipe_close(card);		return 0;}/*============================================================================ * Send a packet on a network interface. * o set tbusy flag (marks start of the transmission) to block a timer-based *   transmit from overlapping. * o check link state. If link is not up, then drop the packet. * o execute adapter send command. * o free socket buffer * * Return:	0	complete (socket buffer must be freed) *		non-0	packet may be re-transmitted (tbusy must be set) * * Notes: * 1. This routine is called either by the protocol stack or by the "net *    bottom half" (with interrupts enabled). * 2. Setting tbusy flag will inhibit further transmit requests from the *    protocol stack and can be used for flow control with protocol layer. */static int if_send(struct sk_buff* skb, struct net_device* dev){	chdlc_private_area_t *chdlc_priv_area = dev->priv;	sdla_t *card = chdlc_priv_area->card;	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;	INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct;	int udp_type = 0;	unsigned long smp_flags;	int err=0;	netif_stop_queue(dev);		if (skb == NULL){		/* If we get here, some higher layer thinks we've missed an		 * tx-done interrupt.		 */		printk(KERN_INFO "%s: Received NULL skb buffer! interface %s got kicked!\n",			card->devname, dev->name);		netif_wake_queue(dev);		return 0;	}   	if (ntohs(skb->protocol) != htons(PVC_PROT)){		/* check the udp packet type */				udp_type = udp_pkt_type(skb, card);		if (udp_type == UDP_CPIPE_TYPE){                        if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev,                                chdlc_priv_area)){				chdlc_int->interrupt_permission |=					APP_INT_ON_TIMER;			}			netif_start_queue(dev);			return 0;		}        }	/* Lock the 508 Card: SMP is supported */      	if(card->hw.type != SDLA_S514){		s508_lock(card,&smp_flags);	}     	if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)){			printk(KERN_INFO "%s: Critical in if_send: %lx\n",					card->wandev.name,card->wandev.critical);                ++card->wandev.stats.tx_dropped;		netif_start_queue(dev);		goto if_send_crit_exit;	}	if (card->wandev.state != WAN_CONNECTED){		++card->wandev.stats.tx_dropped;		netif_start_queue(dev);		goto if_send_crit_exit;	}		if (chdlc_send(card, skb->data, skb->len)){		netif_stop_queue(dev);	}else{		++card->wandev.stats.tx_packets;       		card->wandev.stats.tx_bytes += skb->len;		dev->trans_start = jiffies;		netif_start_queue(dev);	}	if_send_crit_exit:	if (!(err=netif_queue_stopped(dev))){                dev_kfree_skb_any(skb);	}else{		chdlc_priv_area->tick_counter = jiffies;		chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;	}	clear_bit(SEND_CRIT, (void*)&card->wandev.critical);	if(card->hw.type != SDLA_S514){		s508_unlock(card,&smp_flags);	}	return err;}/*============================================================================ * Reply to UDP Management system. * Return length of reply. */static int reply_udp( unsigned char *data, unsigned int mbox_len ){	unsigned short len, udp_length, temp, ip_length;	unsigned long ip_temp;	int even_bound = 0;  	chdlc_udp_pkt_t *c_udp_pkt = (chdlc_udp_pkt_t *)data;	 	/* Set length of packet */	len = sizeof(ip_pkt_t)+ 	      sizeof(udp_pkt_t)+	      sizeof(wp_mgmt_t)+	      sizeof(cblock_t)+	      sizeof(trace_info_t)+ 	      mbox_len;	/* fill in UDP reply */	c_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;   	/* fill in UDP length */	udp_length = sizeof(udp_pkt_t)+ 		     sizeof(wp_mgmt_t)+		     sizeof(cblock_t)+	             sizeof(trace_info_t)+		     mbox_len;  	/* put it on an even boundary */	if ( udp_length & 0x0001 ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -