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

📄 sdla_chdlc.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif	/* Get Multicast Information */	chdlc_priv_area->mc = conf->mc;	/* prepare network device data space for registration */#ifdef LINUX_2_4	strcpy(dev->name,card->u.c.if_name);#else	dev->name = (char *)kmalloc(strlen(card->u.c.if_name) + 2, GFP_KERNEL); 	sprintf(dev->name, "%s", card->u.c.if_name);#endif	dev->init = &if_init;	dev->priv = chdlc_priv_area;	/* Initialize the polling task routine */#ifndef LINUX_2_4	chdlc_priv_area->poll_task.next = NULL;#endif	chdlc_priv_area->poll_task.sync=0;	chdlc_priv_area->poll_task.routine = (void*)(void*)chdlc_poll;	chdlc_priv_area->poll_task.data = dev;	/* Initialize the polling delay timer */	init_timer(&chdlc_priv_area->poll_delay_timer);	chdlc_priv_area->poll_delay_timer.data = (unsigned long)dev;	chdlc_priv_area->poll_delay_timer.function = chdlc_poll_delay;		printk(KERN_INFO "\n");	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 (netdevice_t* dev)	{	chdlc_private_area_t* chdlc_priv_area = dev->priv;	sdla_t* card = chdlc_priv_area->card;	wan_device_t* wandev = &card->wandev;#ifdef LINUX_2_0	int i;#endif	/* Initialize device driver entry points */	dev->open		= &if_open;	dev->stop		= &if_close;	dev->hard_header	= &if_header;	dev->rebuild_header	= &if_rebuild_hdr;	dev->hard_start_xmit	= &if_send;	dev->get_stats		= &if_stats;#ifdef LINUX_2_4	dev->tx_timeout		= &if_tx_timeout;	dev->watchdog_timeo	= TX_TIMEOUT;#endif		/* Initialize media-specific parameters */	dev->flags		|= IFF_POINTOPOINT;	dev->flags		|= IFF_NOARP;	/* Enable Mulitcasting if user selected */	if (chdlc_priv_area->mc == WANOPT_YES){		dev->flags 	|= IFF_MULTICAST;	}	#ifdef LINUX_2_0	dev->family		= AF_INET;#endif		if (chdlc_priv_area->true_if_encoding){#if defined(LINUX_2_1) || defined(LINUX_2_4)		dev->type	= ARPHRD_HDLC; /* This breaks the tcpdump */#else		dev->type	= ARPHRD_PPP;#endif	}else{		dev->type	= ARPHRD_PPP;	}		dev->mtu		= card->wandev.mtu;	/* for API usage, add the API header size to the requested MTU size */	if(card->u.c.usedby == API) {		dev->mtu += sizeof(api_tx_hdr_t);	} 	dev->hard_header_len	= CHDLC_HDR_LEN;	/* 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 too low packets will not be retransmitted          * by stack.	 */        dev->tx_queue_len = 100;   	/* Initialize socket buffers */#if !defined(LINUX_2_1) && !defined(LINUX_2_4)        for (i = 0; i < DEV_NUMBUFFS; ++i)                skb_queue_head_init(&dev->buffs[i]);#endif	return 0;}/*============================================================================ * 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 (netdevice_t* dev){	chdlc_private_area_t* chdlc_priv_area = dev->priv;	sdla_t* card = chdlc_priv_area->card;	struct timeval tv;	int err = 0;	/* Only one open per interface is allowed */	if (is_dev_running(dev))		return -EBUSY;#if defined(LINUX_2_1) || defined(LINUX_2_4)	/* Initialize the task queue */	chdlc_priv_area->tq_working=0;#ifndef LINUX_2_4	chdlc_priv_area->common.wanpipe_task.next = NULL;#endif	chdlc_priv_area->common.wanpipe_task.sync = 0;	chdlc_priv_area->common.wanpipe_task.routine = (void *)(void *)chdlc_bh;	chdlc_priv_area->common.wanpipe_task.data = dev;	/* Allocate and initialize BH circular buffer */	/* Add 1 to MAX_BH_BUFF so we don't have test with (MAX_BH_BUFF-1) */	chdlc_priv_area->bh_head = kmalloc((sizeof(bh_data_t)*(MAX_BH_BUFF+1)),GFP_ATOMIC);	memset(chdlc_priv_area->bh_head,0,(sizeof(bh_data_t)*(MAX_BH_BUFF+1)));	atomic_set(&chdlc_priv_area->bh_buff_used, 0);#endif 	do_gettimeofday(&tv);	chdlc_priv_area->router_start_time = tv.tv_sec;#ifdef LINUX_2_4	netif_start_queue(dev);#else	dev->interrupt = 0;	dev->tbusy = 0;	dev->start = 1;#endif	wanpipe_open(card);	/* TTY is configured during wanpipe_set_termios	 * call, not here */	if (card->tty_opt)		return err;		set_bit(0,&chdlc_priv_area->config_chdlc);	chdlc_priv_area->config_chdlc_timeout=jiffies;	del_timer(&chdlc_priv_area->poll_delay_timer);	/* Start the CHDLC configuration after 1sec delay.	 * This will give the interface initilization time	 * to finish its configuration */	chdlc_priv_area->poll_delay_timer.expires=jiffies+HZ;	add_timer(&chdlc_priv_area->poll_delay_timer);	return err;}/*============================================================================ * Close network interface. * o if this is the last close, then disable communications and interrupts. * o reset flags. */static int if_close (netdevice_t* dev){	chdlc_private_area_t* chdlc_priv_area = dev->priv;	sdla_t* card = chdlc_priv_area->card;#if defined(LINUX_2_1) || defined(LINUX_2_4)	if (chdlc_priv_area->bh_head){		int i;		struct sk_buff *skb;			for (i=0; i<(MAX_BH_BUFF+1); i++){			skb = ((bh_data_t *)&chdlc_priv_area->bh_head[i])->skb;			if (skb != NULL){                		wan_dev_kfree_skb(skb, FREE_READ);			}		}		kfree(chdlc_priv_area->bh_head);		chdlc_priv_area->bh_head=NULL;	}#endif	stop_net_queue(dev);#ifndef LINUX_2_4	dev->start=0;#endif	wanpipe_close(card);	del_timer(&chdlc_priv_area->poll_delay_timer);	return 0;}static void disable_comm (sdla_t *card){	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;		if (card->u.c.comm_enabled){		chdlc_disable_comm_shutdown (card);	}else{		flags->interrupt_info_struct.interrupt_permission = 0;		}#if defined(LINUX_2_4) || defined(LINUX_2_1)		if (!tty_init_cnt)		return;	if (card->tty_opt){		struct serial_state * state;		if (!(--tty_init_cnt)){			int e1,e2;			*serial_driver.refcount=0;						if ((e1 = tty_unregister_driver(&serial_driver)))				printk("SERIAL: failed to unregister serial driver (%d)\n",				       e1);			if ((e2 = tty_unregister_driver(&callout_driver)))				printk("SERIAL: failed to unregister callout driver (%d)\n", 				       e2);			printk(KERN_INFO "%s: Unregistering TTY Driver, Major %i\n",					card->devname,WAN_TTY_MAJOR);		}		card->tty=NULL;		tty_card_map[card->tty_minor]=NULL;		state = &rs_table[card->tty_minor];		memset(state,0,sizeof(state));	}#endif	return;}/*============================================================================ * Build media header. * * The trick here is to put packet type (Ethertype) into 'protocol' field of * the socket buffer, so that we don't forget it.  If packet type is not * supported, set skb->protocol to 0 and discard packet later. * * Return:	media header length. */static int if_header (struct sk_buff* skb, netdevice_t* dev,	unsigned short type, void* daddr, void* saddr, unsigned len){	skb->protocol = htons(type);	return CHDLC_HDR_LEN;}#ifdef LINUX_2_4/*============================================================================ * Handle transmit timeout event from netif watchdog */static void if_tx_timeout (netdevice_t *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);}#endif/*============================================================================ * Re-build media header. * * Return:	1	physical address resolved. *		0	physical address not resolved */#if defined(LINUX_2_1) || defined(LINUX_2_4)static int if_rebuild_hdr (struct sk_buff *skb){	return 1;}#elsestatic int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr,                           struct sk_buff* skb){        return 1;}#endif/*============================================================================ * 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, netdevice_t* 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;#ifdef LINUX_2_4	netif_stop_queue(dev);#endif		if (skb == NULL){		/* If we get here, some higher layer thinks we've missed an		 * tx-done interrupt.		 */		printk(KERN_INFO "%s: interface %s got kicked!\n",			card->devname, dev->name);		wake_net_dev(dev);		return 0;	}#ifndef LINUX_2_4	if (dev->tbusy){		/* 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;		if((jiffies - chdlc_priv_area->tick_counter) < (5 * HZ)) {			return 1;		}		printk (KERN_INFO "%s: Transmit timeout !\n",			card->devname);		/* unbusy the interface */		clear_bit(0,&dev->tbusy);	}#endif   	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;			}			start_net_queue(dev);			return 0;		}		/* check to see if the source IP address is a broadcast or */		/* multicast IP address */                if(chk_bcast_mcast_addr(card, dev, skb)){			++card->wandev.stats.tx_dropped;			wan_dev_kfree_skb(skb,FREE_WRITE);			start_net_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;		start_net_queue(dev);		goto if_send_exit_crit;	}	if(card->u.c.state != WAN_CONNECTED){       		++card->wandev.stats.tx_dropped;		start_net_queue(dev);			}else if(!skb->protocol){        	++card->wandev.stats.tx_errors;		start_net_queue(dev);			}else {		void* data = skb->data;		unsigned len = skb->len;		unsigned char attr;		/* If it's an API packet pull off the API		 * header. Also check that the packet size		 * is larger than the API header	         */		if (card->u.c.usedby == API){			api_tx_hdr_t* api_tx_hdr;			/* discard the frame if we are configured for */			/* 'receive only' mode or if there is no data */			if (card->u.c.receive_only ||				(len <= sizeof(api_tx_hdr_t))) {								++card->wandev.stats.tx_dropped;				start_net_queue(dev);				goto if_send_exit_crit;			}							api_tx_hdr = (api_tx_hdr_t *)data;			attr = api_tx_hdr->attr;			data += sizeof(api_tx_hdr_t);			len -= sizeof(api_tx_hdr_t);

⌨️ 快捷键说明

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