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

📄 sdla_x25.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
 */static int del_if (wan_device_t* wandev, struct device* dev){	if (dev->priv)	{		kfree(dev->priv);		dev->priv = NULL;	}	return 0;}/****** WANPIPE-specific entry points ***************************************//*============================================================================ * Execute adapter interface command. */static int wpx_exec (struct sdla* card, void* u_cmd, void* u_data){	TX25Mbox* mbox = card->mbox;	int retry = MAX_CMD_RETRY;	int err, len;	TX25Cmd cmd;	if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd)))		return -EFAULT;			/* execute command */	do	{		memcpy(&mbox->cmd, &cmd, sizeof(cmd));		if (cmd.length)		{			if(copy_from_user((void*)&mbox->data, u_data, cmd.length))				return-EFAULT;		}		if (sdla_exec(mbox))			err = mbox->cmd.result		;		else return -EIO;	}	while (err && retry-- && x25_error(card, err, cmd.command, cmd.lcn));	/* return result */	if(copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(TX25Cmd)))		return -EFAULT;	len = mbox->cmd.length;	if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len))		return -EFAULT;	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 device* dev){	x25_channel_t* chan = dev->priv;	sdla_t* card = chan->card;	wan_device_t* wandev = &card->wandev;	/* 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;	/* Initialize media-specific parameters */	dev->type		= 30;		/* ARP h/w type */	dev->mtu		= X25_CHAN_MTU;	dev->hard_header_len	= X25_HRDHDR_SZ; /* media header length */	dev->addr_len		= 2;		/* hardware address length */	if (!chan->svc)		*(unsigned short*)dev->dev_addr = htons(chan->lcn);	/* Initialize hardware parameters (just for reference) */	dev->irq	= wandev->irq;	dev->dma	= wandev->dma;	dev->base_addr	= wandev->ioport;	dev->mem_start	= (unsigned long)wandev->maddr;	dev->mem_end	= dev->mem_end + wandev->msize - 1;        /* Set transmit buffer queue length */        dev->tx_queue_len = 10;	/* Initialize socket buffers */		dev_init_buffers(dev);	set_chan_state(dev, WAN_DISCONNECTED);	return 0;}/*============================================================================ * Open network interface. * o prevent module from unloading by incrementing use count * o if link is disconnected then initiate connection * * Return 0 if O.k. or errno. */static int if_open (struct device* dev){	x25_channel_t* chan = dev->priv;	sdla_t* card = chan->card;	if (dev->start)		return -EBUSY;		/* only one open is allowed */		if (test_and_set_bit(0, (void*)&card->wandev.critical))		return -EAGAIN;	dev->interrupt = 0;	dev->tbusy = 0;	dev->start = 1;	wanpipe_open(card);	/* If this is the first open, initiate physical connection */	if (card->open_cnt == 1)		connect(card);	card->wandev.critical = 0;	return 0;}/*============================================================================ * Close network interface. * o reset flags. * o if there's no more open channels then disconnect physical link. */static int if_close (struct device* dev){	x25_channel_t* chan = dev->priv;	sdla_t* card = chan->card;	if (test_and_set_bit(0, (void*)&card->wandev.critical))		return -EAGAIN;	dev->start = 0;	if ((chan->state == WAN_CONNECTED) || (chan->state == WAN_CONNECTING))		chan_disc(dev);			wanpipe_close(card);	/* If this is the last close, disconnect physical link */	if (!card->open_cnt)		disconnect(card);			card->wandev.critical = 0;	return 0;}/*============================================================================ * Build media header. * o encapsulate packet according to encapsulation type. * * The trick here is to put packet type (Ethertype) into 'protocol' field of * the socket buffer, so that we don't forget it.  If encapsulation fails, * set skb->protocol to 0 and discard packet later. * * Return:	media header length. */static int if_header (struct sk_buff* skb, struct device* dev,	unsigned short type, void* daddr, void* saddr, unsigned len){	x25_channel_t* chan = dev->priv;	int hdr_len = dev->hard_header_len;	skb->protocol = type;	if (!chan->protocol)	{		hdr_len = wanrouter_encapsulate(skb, dev);		if (hdr_len < 0)		{			hdr_len = 0;			skb->protocol = 0;		}	}	return hdr_len;}/*============================================================================ * Re-build media header. * * Return:	1	physical address resolved. *		0	physical address not resolved */ static int if_rebuild_hdr (struct sk_buff* skb){	struct device *dev=skb->dev;	x25_channel_t* chan = dev->priv;	sdla_t* card = chan->card;	printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n",		card->devname, dev->name);	return 1;}/*============================================================================ * Send a packet on a network interface. * o set tbusy flag (marks start of the transmission). * o check link state. If link is not up, then drop the packet. * o check channel status. If it's down then initiate a call. * o pass a packet to corresponding WAN device. * 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 device* dev){	x25_channel_t* chan = dev->priv;	sdla_t* card = chan->card;	struct device *dev2;	TX25Status* status = card->flags;	unsigned long host_cpu_flags;	if (dev->tbusy)	{		++chan->ifstats.rx_dropped;			if ((jiffies - chan->tick_counter) < (5*HZ))		{			return dev->tbusy;		}		printk(KERN_INFO "%s: Transmit time out %s!\n",			card->devname, dev->name)		;		for( dev2 = card->wandev.dev; dev2; dev2 = dev2->slave)		{	        	dev2->tbusy = 0;		}	}	chan->tick_counter = jiffies;	disable_irq(card->hw.irq);	++card->irq_dis_if_send_count;	if (test_and_set_bit(0, (void*)&card->wandev.critical)) 	{		printk(KERN_INFO "Hit critical in if_send()!\n");		if (card->wandev.critical == CRITICAL_IN_ISR) 		{			card->wandev.enable_tx_int = 1;			dev->tbusy = 1;						save_flags(host_cpu_flags);                        cli();                        if ((!(--card->irq_dis_if_send_count)) &&                                        (!card->irq_dis_poll_count))                                enable_irq(card->hw.irq);                        restore_flags(host_cpu_flags);						return dev->tbusy;		}		dev_kfree_skb(skb);				save_flags(host_cpu_flags);                cli();                if ((!(--card->irq_dis_if_send_count)) &&                                         (!card->irq_dis_poll_count))                        enable_irq(card->hw.irq);                restore_flags(host_cpu_flags);		return dev->tbusy;	}	/* Below is only until we have per-channel IPX going.... */	if(!(chan->svc))		chan->protocol = skb->protocol;	if (card->wandev.state != WAN_CONNECTED)		++chan->ifstats.tx_dropped;	/* Below is only until we have per-channel IPX going.... */	else if ( (chan->svc) && (chan->protocol && (chan->protocol != skb->protocol)))	{		printk(KERN_INFO			"%s: unsupported Ethertype 0x%04X on interface %s!\n",			card->devname, skb->protocol, dev->name);		++chan->ifstats.tx_errors;	}	else switch (chan->state)	{		case WAN_DISCONNECTED:			/* Try to establish connection. If succeded, then start			 * transmission, else drop a packet.			 */			if (chan_connect(dev) != 0)			{				++chan->ifstats.tx_dropped;				++card->wandev.stats.tx_dropped;				break;			}			/* fall through */		case WAN_CONNECTED:			if( skb->protocol == ETH_P_IPX ) 			{				if(card->wandev.enable_IPX) 				{					switch_net_numbers( skb->data, 						card->wandev.network_number, 0);				}				else 				{					++card->wandev.stats.tx_dropped;					++chan->ifstats.tx_dropped;					goto tx_done;				}			}			dev->trans_start = jiffies;			if(chan_send(dev, skb))			{				dev->tbusy = 1;				status->imask |= 0x2;			}			break;		default:			++chan->ifstats.tx_dropped;				++card->wandev.stats.tx_dropped;	}tx_done:	if (!dev->tbusy)		dev_kfree_skb(skb);	card->wandev.critical = 0;	save_flags(host_cpu_flags);        cli();        if ((!(--card->irq_dis_if_send_count)) && (!card->irq_dis_poll_count))                enable_irq(card->hw.irq);        restore_flags(host_cpu_flags);	return dev->tbusy;}/*============================================================================ * Get Ethernet-style interface statistics. * Return a pointer to struct net_device_stats */ static struct net_device_stats* if_stats (struct device* dev){	x25_channel_t* chan = dev->priv;	if(chan==NULL)		return NULL;	return &chan->ifstats;}/****** Interrupt Handlers **************************************************//*============================================================================ * X.25 Interrupt Service Routine. */ static void wpx_isr (sdla_t* card){	TX25Status* status = card->flags;	struct device *dev;	unsigned long host_cpu_flags;	card->in_isr = 1;	card->buff_int_mode_unbusy = 0;	if (test_and_set_bit(0, (void*)&card->wandev.critical)) 	{ 		printk(KERN_INFO "wpx_isr: %s, wandev.critical set to 0x%02X, int type = 0x%02X\n", card->devname, card->wandev.critical, status->iflags);		card->in_isr = 0;		return;	}	/* For all interrupts set the critical flag to CRITICAL_RX_INTR.         * If the if_send routine is called with this flag set it will set         * the enable transmit flag to 1. (for a delayed interrupt)         */	card->wandev.critical = CRITICAL_IN_ISR;	switch (status->iflags)	{		case 0x01:		/* receive interrupt */			rx_intr(card);			break;		case 0x02:		/* transmit interrupt */			tx_intr(card);			card->buff_int_mode_unbusy = 1;			status->imask &= ~0x2;			break;		case 0x04:		/* modem status interrupt */			status_intr(card);			break;		case 0x10:		/* network event interrupt */			event_intr(card);			break;		default:		/* unwanted interrupt */			spur_intr(card);	}	card->wandev.critical = CRITICAL_INTR_HANDLED;	if( card->wandev.enable_tx_int)	{		card->wandev.enable_tx_int = 0;		status->imask |= 0x2;	}	save_flags(host_cpu_flags);	cli();	card->in_isr = 0;	status->iflags = 0;	/* clear interrupt condition */	card->wandev.critical = 0;	restore_flags(host_cpu_flags);	if(card->buff_int_mode_unbusy)	{		for(dev = card->wandev.dev; dev; dev = dev->slave)		{			if(((x25_channel_t*)dev->priv)->devtint)			{				mark_bh(NET_BH);				return;			}			}	}}/*============================================================================ * Receive interrupt handler. * This routine handles fragmented IP packets using M-bit according to the * RFC1356. * o map ligical channel number to network interface. * o allocate socket buffer or append received packet to the existing one. * o if M-bit is reset (i.e. it's the last packet in a sequence) then  *   decapsulate packet and pass socket buffer to the protocol stack. * * Notes: * 1. When allocating a socket buffer, if M-bit is set then more data is *    comming and we have to allocate buffer for the maximum IP packet size *    expected on this channel. * 2. If something goes wrong and X.25 packet has to be dropped (e.g. no *    socket buffers available) the whole packet sequence must be discarded. */static void rx_intr (sdla_t* card){	TX25Mbox* rxmb = card->rxmb;	unsigned lcn = rxmb->cmd.lcn;		/* logical channel number */	unsigned len = rxmb->cmd.length;	/* packet length */	unsigned qdm = rxmb->cmd.qdm;		/* Q,D and M bits */	wan_device_t* wandev = &card->wandev;	struct device* dev = get_dev_by_lcn(wandev, lcn);	x25_channel_t* chan;	struct sk_buff* skb;	void* bufptr;	if (dev == NULL)	{

⌨️ 快捷键说明

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