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

📄 sdla_x25.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
		}		else mbox->cmd.length  = 1;		mbox->cmd.command = X25_SET_INTERRUPT_MODE;		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;	} while (err && retry-- && x25_error(card, err, X25_SET_INTERRUPT_MODE, 0)) ;	return err;}/*============================================================================ * Read X.25 channel configuration. */static int x25_get_chan_conf (sdla_t* card, x25_channel_t* chan){	TX25Mbox* mbox = card->mbox;  	int retry = MAX_CMD_RETRY;	int lcn = chan->lcn;	int err;	do	{		memset(&mbox->cmd, 0, sizeof(TX25Cmd));		mbox->cmd.lcn     = lcn;		mbox->cmd.command = X25_READ_CHANNEL_CONFIG;		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;	} while (err && retry-- && x25_error(card, err, X25_READ_CHANNEL_CONFIG, lcn));	if (!err)	{		TX25Status* status = card->flags;		/* calculate an offset into the array of status bytes */		if (card->u.x.hi_svc <= 255) 			chan->ch_idx = lcn - 1;		else		{			int offset;			switch (mbox->data[0] && 0x1F)			{				case 0x01:					offset = status->pvc_map; break;				case 0x03:					offset = status->icc_map; break;				case 0x07:					offset = status->twc_map; break;				case 0x0B: 					offset = status->ogc_map; break;				default: 					offset = 0;			}			chan->ch_idx = lcn - 1 - offset;		}		/* get actual transmit packet size on this channel */		switch(mbox->data[1] & 0x38)		{			case 0x00:				chan->tx_pkt_size = 16;				break;			case 0x08:				chan->tx_pkt_size = 32;				break;			case 0x10:				chan->tx_pkt_size = 64;				break;			case 0x18:				chan->tx_pkt_size = 128;				break;			case 0x20:				chan->tx_pkt_size = 256;				break;			case 0x28:				chan->tx_pkt_size = 512;				break;			case 0x30:				chan->tx_pkt_size = 1024;				break;		}		printk(KERN_INFO "%s: X.25 packet size on LCN %d is %d.\n",			card->devname, lcn, chan->tx_pkt_size);	}	return err;}/*============================================================================ * Place X.25 call. */static int x25_place_call (sdla_t* card, x25_channel_t* chan){	TX25Mbox* mbox = card->mbox;  	int retry = MAX_CMD_RETRY;	int err;	char str[64];	sprintf(str, "-d%s -uCC", chan->addr);	do	{		memset(&mbox->cmd, 0, sizeof(TX25Cmd));		strcpy(mbox->data, str);		mbox->cmd.length  = strlen(str);		mbox->cmd.command = X25_PLACE_CALL;		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;	} while (err && retry-- && x25_error(card, err, X25_PLACE_CALL, 0));	if (!err)	{		chan->lcn = mbox->cmd.lcn;		chan->protocol = ETH_P_IP;	}	return err;}/*============================================================================ * Accept X.25 call. */static int x25_accept_call (sdla_t* card, int lcn, int qdm){	TX25Mbox* mbox = card->mbox;  	int retry = MAX_CMD_RETRY;	int err;	do	{		memset(&mbox->cmd, 0, sizeof(TX25Cmd));		mbox->cmd.lcn     = lcn;		mbox->cmd.qdm     = qdm;		mbox->cmd.command = X25_ACCEPT_CALL;		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;	} while (err && retry-- && x25_error(card, err, X25_ACCEPT_CALL, lcn));	return err;}/*============================================================================ * Clear X.25 call. */static int x25_clear_call (sdla_t* card, int lcn, int cause, int diagn){	TX25Mbox* mbox = card->mbox;  	int retry = MAX_CMD_RETRY;	int err;	do	{		memset(&mbox->cmd, 0, sizeof(TX25Cmd));		mbox->cmd.lcn     = lcn;		mbox->cmd.cause   = cause;		mbox->cmd.diagn   = diagn;		mbox->cmd.command = X25_CLEAR_CALL;		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;	} while (err && retry-- && x25_error(card, err, X25_CLEAR_CALL, lcn));	return err;}/*============================================================================ * Send X.25 data packet. */static int x25_send (sdla_t* card, int lcn, int qdm, int len, void* buf){	TX25Mbox* mbox = card->mbox;  	int retry = MAX_CMD_RETRY;	int err;		do	{		memset(&mbox->cmd, 0, sizeof(TX25Cmd));		memcpy(mbox->data, buf, len);		mbox->cmd.length  = len;		mbox->cmd.lcn     = lcn;		mbox->cmd.qdm     = qdm;		mbox->cmd.command = X25_WRITE;		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;	} while (err && retry-- && x25_error(card, err, X25_WRITE, lcn));	return err;}/*============================================================================ * Fetch X.25 asynchronous events. */static int x25_fetch_events (sdla_t* card){	TX25Status* status = card->flags;	TX25Mbox* mbox = card->mbox;	int err = 0;	if (status->gflags & 0x20)	{		memset(&mbox->cmd, 0, sizeof(TX25Cmd));		mbox->cmd.command = X25_IS_DATA_AVAILABLE;		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; 		if (err) 			x25_error(card, err, X25_IS_DATA_AVAILABLE, 0);	}	return err;}/*============================================================================ * X.25 asynchronous event/error handler. *	This routine is called each time interface command returns non-zero *	return code to handle X.25 asynchronous events and common errors. *	Return non-zero to repeat command or zero to cancel it. * * Notes: * 1. This function may be called recursively, as handling some of the *    asynchronous events (e.g. call request) requires execution of the *    interface command(s) that, in turn, may also return asynchronous *    events.  To avoid re-entrancy problems we copy mailbox to dynamically *    allocated memory before processing events. */static int x25_error (sdla_t* card, int err, int cmd, int lcn){	int retry = 1;	unsigned dlen = ((TX25Mbox*)card->mbox)->cmd.length;	TX25Mbox* mb;	mb = kmalloc(sizeof(TX25Mbox) + dlen, GFP_ATOMIC);	if (mb == NULL)	{		printk(KERN_ERR "%s: x25_error() out of memory!\n",			card->devname);		return 0;	}	memcpy(mb, card->mbox, sizeof(TX25Mbox) + dlen);	switch (err)	{		case 0x40:	/* X.25 asynchronous packet was received */			mb->data[dlen] = '\0';			switch (mb->cmd.pktType & 0x7F)			{				case 0x30:		/* incoming call */					retry = incoming_call(card, cmd, lcn, mb);					break;				case 0x31:		/* connected */					retry = call_accepted(card, cmd, lcn, mb);					break;				case 0x02:		/* call clear request */					retry = call_cleared(card, cmd, lcn, mb);					break;				case 0x04:		/* reset request */					printk(KERN_INFO "%s: X.25 reset request on LCN %d! "						"Cause:0x%02X Diagn:0x%02X\n",						card->devname, mb->cmd.lcn, mb->cmd.cause,						mb->cmd.diagn);					break;				case 0x08:		/* restart request */					retry = restart_event(card, cmd, lcn, mb);					break;				default:					printk(KERN_INFO "%s: X.25 event 0x%02X on LCN %d! "						"Cause:0x%02X Diagn:0x%02X\n",						card->devname, mb->cmd.pktType,						mb->cmd.lcn, mb->cmd.cause, mb->cmd.diagn);			}			break;		case 0x41:	/* X.25 protocol violation indication */			printk(KERN_INFO				"%s: X.25 protocol violation on LCN %d! "				"Packet:0x%02X Cause:0x%02X Diagn:0x%02X\n",				card->devname, mb->cmd.lcn,				mb->cmd.pktType & 0x7F, mb->cmd.cause, mb->cmd.diagn);			break;		case 0x42:	/* X.25 timeout */			retry = timeout_event(card, cmd, lcn, mb);			break;		case 0x43:	/* X.25 retry limit exceeded */			printk(KERN_INFO				"%s: exceeded X.25 retry limit on LCN %d! "				"Packet:0x%02X Diagn:0x%02X\n", card->devname,				mb->cmd.lcn, mb->cmd.pktType, mb->cmd.diagn);			break;		case 0x08:	/* modem failure */			printk(KERN_INFO "%s: modem failure!\n", card->devname);			break;		case 0x09:	/* N2 retry limit */			printk(KERN_INFO "%s: exceeded HDLC retry limit!\n",				card->devname);			break;		case 0x06:	/* unnumbered frame was received while in ABM */			printk(KERN_INFO "%s: received Unnumbered frame 0x%02X!\n",				card->devname, mb->data[0]);			break;		case CMD_TIMEOUT:			printk(KERN_ERR "%s: command 0x%02X timed out!\n",				card->devname, cmd);			retry = 0;	/* abort command */			break;		default:			printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",				card->devname, cmd, err);			retry = 0;	/* abort command */	}	kfree(mb);	return retry;}/****** X.25 Asynchronous Event Handlers ************************************* * These functions are called by the x25_error() and should return 0, if * the command resulting in the asynchronous event must be aborted. *//*============================================================================ * Handle X.25 incoming call request. *	RFC 1356 establishes the following rules: *	1. The first octet in the Call User Data (CUD) field of the call *	   request packet contains NLPID identifying protocol encapsulation. *	2. Calls MUST NOT be accepted unless router supports requested *	   protocol encapsulation. *	3. A diagnostic code 249 defined by ISO/IEC 8208 may be used when *	   clearing a call because protocol encapsulation is not supported. *	4. If an incoming call is received while a call request is pending *	   (i.e. call collision has occurred), the incoming call shall be *	   rejected and call request shall be retried. */static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb){	wan_device_t* wandev = &card->wandev;	int new_lcn = mb->cmd.lcn;	struct device* dev = get_dev_by_lcn(wandev, new_lcn);	x25_channel_t* chan = NULL;	int accept = 0;		/* set to '1' if o.k. to accept call */	x25_call_info_t* info;	/* Make sure there is no call collision */	if (dev != NULL)	{		printk(KERN_INFO			"%s: X.25 incoming call collision on LCN %d!\n",			card->devname, new_lcn);		x25_clear_call(card, new_lcn, 0, 0);		return 1;	}	/* Make sure D bit is not set in call request */	if (mb->cmd.qdm & 0x02)	{		printk(KERN_INFO			"%s: X.25 incoming call on LCN %d with D-bit set!\n",			card->devname, new_lcn);		x25_clear_call(card, new_lcn, 0, 0);		return 1;	}	/* Parse call request data */	info = kmalloc(sizeof(x25_call_info_t), GFP_ATOMIC);	if (info == NULL)	{		printk(KERN_ERR			"%s: not enough memory to parse X.25 incoming call "			"on LCN %d!\n", card->devname, new_lcn);		x25_clear_call(card, new_lcn, 0, 0);		return 1;	}	parse_call_info(mb->data, info);	printk(KERN_INFO "%s: X.25 incoming call on LCN %d! Call data: %s\n",		card->devname, new_lcn, mb->data);	/* Find available channel */	for (dev = wandev->dev; dev; dev = dev->slave)	{		chan = dev->priv;		if (!chan->svc || (chan->state != WAN_DISCONNECTED))			continue;		if (strcmp(info->src, chan->addr) == 0)			break;	        /* If just an '@' is specified, accept all incoming calls */	        if (strcmp(chan->addr, "") == 0)	                break;	}	if (dev == NULL)	{		printk(KERN_INFO "%s: no channels available!\n",			card->devname);		x25_clear_call(card, new_lcn, 0, 0);	}	/* Check requested protocol encapsulation */	else if (info->nuser == 0)	{		printk(KERN_INFO			"%s: no user data in incoming call on LCN %d!\n",			card->devname, new_lcn);		x25_clear_call(card, new_lcn, 0, 0);	}	else switch (info->user[0])	{		case 0:		/* multiplexed */			chan->protocol = 0;			accept = 1;			break;		case NLPID_IP:	/* IP datagrams */			chan->protocol = ETH_P_IP;			accept = 1;			break;		case NLPID_SNAP: /* IPX datagrams */			chan->protocol = ETH_P_IPX;			accept = 1;			break;		default:			printk(KERN_INFO				"%s: unsupported NLPID 0x%02X in incoming call "				"on LCN %d!\n", card->devname, info->user[0], new_lcn);			x25_clear_call(card, new_lcn, 0, 249);	}	if (accept && (x25_accept_call(card, new_lcn, 0) == CMD_OK))	{		chan->lcn = new_lcn;		if (x25_get_chan_conf(card, chan) == CMD_OK)			set_chan_state(dev, WAN_CONNECTED);		else			x25_clear_call(card, new_lcn, 0, 0);	}	kfree(info);	return 1;}/*============================================================================ * Handle accepted call. */static int call_accepted (sdla_t* card, int cmd, int lcn, TX25Mbox* mb){	unsigned new_lcn = mb->cmd.lcn;	struct device* dev = get_dev_by_lcn(&card->wandev, new_lcn);	x25_channel_t* chan;	printk(KERN_INFO "%s: X.25 call accepted on LCN %d!\n",		card->devname, new_lcn);	if (dev == NULL)	{		printk(KERN_INFO			"%s: clearing orphaned connection on LCN %d!\n",			card->devname, new_lcn);		x25_clear_call(card, new_lcn, 0, 0);		return 1;	}	/* Get channel configuration and notify router */	chan = dev->priv;	if (x25_get_chan_conf(card, chan) != CMD_OK)	{		x25_clear_call(card, new_lcn, 0, 0);		return 1;	}	set_chan_state(dev, WAN_CONNECTED);	return 1;}/*============================================================================ * Handle cleared call.

⌨️ 快捷键说明

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