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

📄 sdla_x25.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* Invalid channel, discard packet */		printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",			card->devname, lcn);		return;	}	chan = dev->priv;	chan->i_timeout_sofar = jiffies;	if (chan->drop_sequence)	{		if (!(qdm & 0x01)) chan->drop_sequence = 0;		return;	}	skb = chan->rx_skb;	if (skb == NULL)	{		/* Allocate new socket buffer */		int bufsize = (qdm & 0x01) ? dev->mtu : len;		skb = dev_alloc_skb(bufsize + dev->hard_header_len);		if (skb == NULL)		{			printk(KERN_INFO "%s: no socket buffers available!\n",				card->devname);			chan->drop_sequence = 1;	/* set flag */			++chan->ifstats.rx_dropped;			return;		}		skb->dev = dev;		skb->protocol = htons(chan->protocol);		chan->rx_skb = skb;	}	if (skb_tailroom(skb) < len)	{		/* No room for the packet. Call off the whole thing! */		dev_kfree_skb(skb);		chan->rx_skb = NULL;		if (qdm & 0x01) chan->drop_sequence = 1;		printk(KERN_INFO "%s: unexpectedly long packet sequence "			"on interface %s!\n", card->devname, dev->name);		++chan->ifstats.rx_length_errors;		return;	}	/* Append packet to the socket buffer */	bufptr = skb_put(skb, len);	memcpy(bufptr, rxmb->data, len);	if (qdm & 0x01)		return;		/* more data is comming */	dev->last_rx = jiffies;		/* timestamp */	chan->rx_skb = NULL;		/* dequeue packet */	/* Decapsulate packet, if necessary */	if (!skb->protocol && !wanrouter_type_trans(skb, dev))	{		/* can't decapsulate packet */		dev_kfree_skb(skb);		++chan->ifstats.rx_errors;	}	else	{		if( handle_IPXWAN(skb->data, card->devname, card->wandev.enable_IPX, card->wandev.network_number, skb->protocol))		{			if( card->wandev.enable_IPX )			{				if(chan_send(dev, skb))				{					chan->tx_skb = skb;				}				else				{					dev_kfree_skb(skb);				}			}			else			{				/* FIXME: increment IPX packet dropped statistic */			}		}		else		{			netif_rx(skb);			++chan->ifstats.rx_packets;			chan->ifstats.rx_bytes += skb->len;		}	}}/*============================================================================ * Transmit interrupt handler. *	o Release socket buffer *	o Clear 'tbusy' flag */static void tx_intr (sdla_t* card){	struct device *dev;	/* unbusy all devices and then dev_tint(); */	for(dev = card->wandev.dev; dev; dev = dev->slave)	{		((x25_channel_t*)dev->priv)->devtint = dev->tbusy; 		dev->tbusy = 0;	}}/*============================================================================ * Modem status interrupt handler. */static void status_intr (sdla_t* card){}/*============================================================================ * Network event interrupt handler. */static void event_intr (sdla_t* card){}/*============================================================================ * Spurious interrupt handler. * o print a warning * o  * If number of spurious interrupts exceeded some limit, then ??? */static void spur_intr (sdla_t* card){	printk(KERN_INFO "%s: spurious interrupt!\n", card->devname);}/****** Background Polling Routines  ****************************************//*============================================================================ * Main polling routine. * This routine is repeatedly called by the WANPIPE 'thread' to allow for * time-dependent housekeeping work. * * Notes: * 1. This routine may be called on interrupt context with all interrupts *    enabled. Beware! */static void wpx_poll (sdla_t* card){	unsigned long host_cpu_flags;	disable_irq(card->hw.irq);	++card->irq_dis_poll_count;	if (test_and_set_bit(0, (void*)&card->wandev.critical)) 	{ 		printk(KERN_INFO "%s: critical in polling!\n",card->devname);			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;	}	switch(card->wandev.state)	{		case WAN_CONNECTED:			poll_active(card);			break;		case WAN_CONNECTING:			poll_connecting(card);			break;		case WAN_DISCONNECTED:			poll_disconnected(card);	}	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);}/*============================================================================ * Handle physical link establishment phase. * o if connection timed out, disconnect the link. */static void poll_connecting (sdla_t* card){	TX25Status* status = card->flags;	if (status->gflags & X25_HDLC_ABM)	{		wanpipe_set_state(card, WAN_CONNECTED);		x25_set_intr_mode(card, 0x83);	/* enable Rx interrupts */		status->imask &= ~0x2;		/* mask Tx interupts */	}	else if ((jiffies - card->state_tick) > CONNECT_TIMEOUT)	    disconnect(card);}/*============================================================================ * Handle physical link disconnected phase. * o if hold-down timeout has expired and there are open interfaces, connect *   link. */static void poll_disconnected (sdla_t* card){	if (card->open_cnt && ((jiffies - card->state_tick) > HOLD_DOWN_TIME))		connect(card);}/*============================================================================ * Handle active link phase. * o fetch X.25 asynchronous events. * o kick off transmission on all interfaces. */static void poll_active (sdla_t* card){	struct device* dev;	/* Fetch X.25 asynchronous events */	x25_fetch_events(card);	for (dev = card->wandev.dev; dev; dev = dev->slave)	{		x25_channel_t* chan = dev->priv;		struct sk_buff* skb = chan->tx_skb;		/* If there is a packet queued for transmission then kick		 * the channel's send routine. When transmission is complete		 * or if error has occurred, release socket buffer and reset		 * 'tbusy' flag.		 */		if (skb && (chan_send(dev, skb) == 0))		{			chan->tx_skb = NULL;			dev->tbusy = 0;			dev_kfree_skb(skb);		}		/* If SVC has been idle long enough, close virtual circuit */		if(( chan->svc )&&( chan->state == WAN_CONNECTED ))		{			if( (jiffies - chan->i_timeout_sofar) / HZ > chan->idle_timeout )			{				/* Close svc */				printk(KERN_INFO "%s: Closing down Idle link %s on LCN %d\n",card->devname,chan->name,chan->lcn); 				chan->i_timeout_sofar = jiffies;				chan_disc(dev);			}		}	}}/****** SDLA Firmware-Specific Functions ************************************* * Almost all X.25 commands can unexpetedly fail due to so called 'X.25 * asynchronous events' such as restart, interrupt, incoming call request, * call clear request, etc.  They can't be ignored and have to be dealt with * immediately.  To tackle with this problem we execute each interface command * in a loop until good return code is received or maximum number of retries * is reached.  Each interface command returns non-zero return code, an * asynchronous event/error handler x25_error() is called. *//*============================================================================ * Read X.25 firmware version. *	Put code version as ASCII string in str.  */static int x25_get_version (sdla_t* card, char* str){	TX25Mbox* mbox = card->mbox;  	int retry = MAX_CMD_RETRY;	int err;	do	{		memset(&mbox->cmd, 0, sizeof(TX25Cmd));		mbox->cmd.command = X25_READ_CODE_VERSION;		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;	} while (err && retry-- &&		 x25_error(card, err, X25_READ_CODE_VERSION, 0));	if (!err && str)	{		int len = mbox->cmd.length;		memcpy(str, mbox->data, len);		str[len] = '\0';	}	return err;}/*============================================================================ * Configure adapter. */static int x25_configure (sdla_t* card, TX25Config* conf){	TX25Mbox* mbox = card->mbox;  	int retry = MAX_CMD_RETRY;	int err;	do	{		memset(&mbox->cmd, 0, sizeof(TX25Cmd));		memcpy(mbox->data, (void*)conf, sizeof(TX25Config));		mbox->cmd.length  = sizeof(TX25Config);		mbox->cmd.command = X25_SET_CONFIGURATION;		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;	} while (err && retry-- && x25_error(card, err, X25_SET_CONFIGURATION, 0));	return err;}/*============================================================================ * Get communications error statistics. */static int x25_get_err_stats (sdla_t* card){	TX25Mbox* mbox = card->mbox;  	int retry = MAX_CMD_RETRY;	int err;	do	{		memset(&mbox->cmd, 0, sizeof(TX25Cmd));		mbox->cmd.command = X25_HDLC_READ_COMM_ERR;		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;	} while (err && retry-- && x25_error(card, err, X25_HDLC_READ_COMM_ERR, 0));	if (!err)	{		THdlcCommErr* stats = (void*)mbox->data;		card->wandev.stats.rx_over_errors    = stats->rxOverrun;		card->wandev.stats.rx_crc_errors     = stats->rxBadCrc;		card->wandev.stats.rx_missed_errors  = stats->rxAborted;		card->wandev.stats.tx_aborted_errors = stats->txAborted;	}	return err;}/*============================================================================ * Get protocol statistics. */static int x25_get_stats (sdla_t* card){	TX25Mbox* mbox = card->mbox;  	int retry = MAX_CMD_RETRY;	int err;	do	{		memset(&mbox->cmd, 0, sizeof(TX25Cmd));		mbox->cmd.command = X25_READ_STATISTICS;		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;	} while (err && retry-- && x25_error(card, err, X25_READ_STATISTICS, 0));		if (!err)	{		TX25Stats* stats = (void*)mbox->data;		card->wandev.stats.rx_packets = stats->rxData;		card->wandev.stats.tx_packets = stats->rxData;	}	return err;}/*============================================================================ * Close HDLC link. */static int x25_close_hdlc (sdla_t* card){	TX25Mbox* mbox = card->mbox;  	int retry = MAX_CMD_RETRY;	int err;	do	{		memset(&mbox->cmd, 0, sizeof(TX25Cmd));		mbox->cmd.command = X25_HDLC_LINK_CLOSE;		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;	} while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_CLOSE, 0));	return err;}/*============================================================================ * Open HDLC link. */static int x25_open_hdlc (sdla_t* card){	TX25Mbox* mbox = card->mbox;  	int retry = MAX_CMD_RETRY;	int err;	do	{		memset(&mbox->cmd, 0, sizeof(TX25Cmd));		mbox->cmd.command = X25_HDLC_LINK_OPEN;		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;	} while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_OPEN, 0));		return err;}/*============================================================================ * Setup HDLC link. */static int x25_setup_hdlc (sdla_t* card){	TX25Mbox* mbox = card->mbox;  	int retry = MAX_CMD_RETRY;	int err;	do	{		memset(&mbox->cmd, 0, sizeof(TX25Cmd));		mbox->cmd.command = X25_HDLC_LINK_SETUP;		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;	} while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_SETUP, 0));		return err;}/*============================================================================ * Set (raise/drop) DTR. */static int x25_set_dtr (sdla_t* card, int dtr){	TX25Mbox* mbox = card->mbox;  	int retry = MAX_CMD_RETRY;	int err;	do	{		memset(&mbox->cmd, 0, sizeof(TX25Cmd));		mbox->data[0] = 0;		mbox->data[2] = 0;		mbox->data[1] = dtr ? 0x02 : 0x01;		mbox->cmd.length  = 3;		mbox->cmd.command = X25_SET_GLOBAL_VARS;		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;	} while (err && retry-- && x25_error(card, err, X25_SET_GLOBAL_VARS, 0));	return err;}/*============================================================================ * Set interrupt mode. */static int x25_set_intr_mode (sdla_t* card, int mode){	TX25Mbox* mbox = card->mbox;  	int retry = MAX_CMD_RETRY;	int err;	do	{		memset(&mbox->cmd, 0, sizeof(TX25Cmd));		mbox->data[0] = mode;		if (card->hw.fwid == SFID_X25_508)		{			mbox->data[1] = card->hw.irq;			mbox->cmd.length = 2;

⌨️ 快捷键说明

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