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

📄 isdn_net.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
	int si2;	int ematch;	int wret;	int swapped;	int sidx = 0;	isdn_net_dev *p;	isdn_net_phone *n;	ulong flags;	char nr[32];	/* Search name in netdev-chain */	save_flags(flags);	cli();	if (!setup->phone[0]) {		nr[0] = '0';		nr[1] = '\0';		printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n");	} else		strcpy(nr, setup->phone);	si1 = (int) setup->si1;	si2 = (int) setup->si2;	if (!setup->eazmsn[0]) {		printk(KERN_WARNING "isdn_net: Incoming call without CPN, assuming '0'\n");		eaz = "0";	} else		eaz = setup->eazmsn;	if (dev->net_verbose > 1)		printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", nr, si1, si2, eaz);	/* Accept only calls with Si1 = 7 (Data-Transmission) */	if (si1 != 7) {		restore_flags(flags);		if (dev->net_verbose > 1)			printk(KERN_INFO "isdn_net: Service-Indicator not 7, ignored\n");		return 0;	}	n = (isdn_net_phone *) 0;	p = dev->netdev;	ematch = wret = swapped = 0;#ifdef ISDN_DEBUG_NET_ICALL	printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,	       dev->usage[idx]);#endif	while (p) {		int matchret;		isdn_net_local *lp = p->local;		/* If last check has triggered as binding-swap, revert it */		switch (swapped) {			case 2:				isdn_net_swap_usage(idx, sidx);				/* fall through */			case 1:				isdn_net_swapbind(di);				break;		}		swapped = 0;		if (!(matchret = isdn_msncmp(eaz, isdn_map_eaz2msn(lp->msn, di))))			ematch = 1;		/* Remember if more numbers eventually can match */		if (matchret > wret)			wret = matchret;#ifdef ISDN_DEBUG_NET_ICALL		printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",		       lp->name, lp->msn, lp->flags, lp->dialstate);#endif		if ((!matchret) &&                                        /* EAZ is matching   */		    (((!(lp->flags & ISDN_NET_CONNECTED)) &&              /* but not connected */		      (USG_NONE(dev->usage[idx]))) ||                     /* and ch. unused or */		     ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing        */		       (!(lp->flags & ISDN_NET_CALLBACK)))                /* but no callback   */		     )))			 {#ifdef ISDN_DEBUG_NET_ICALL			printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",			       lp->pre_device, lp->pre_channel);#endif			if (dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) {				if ((lp->pre_channel != ch) ||				    (lp->pre_device != di)) {					/* Here we got a problem:					 * If using an ICN-Card, an incoming call is always signaled on					 * on the first channel of the card, if both channels are					 * down. However this channel may be bound exclusive. If the					 * second channel is free, this call should be accepted.					 * The solution is horribly but it runs, so what:					 * We exchange the exclusive bindings of the two channels, the					 * corresponding variables in the interface-structs.					 */					if (ch == 0) {						sidx = isdn_dc2minor(di, 1);#ifdef ISDN_DEBUG_NET_ICALL						printk(KERN_DEBUG "n_fi: ch is 0\n");#endif						if (USG_NONE(dev->usage[sidx])) {							/* Second Channel is free, now see if it is bound							 * exclusive too. */							if (dev->usage[sidx] & ISDN_USAGE_EXCLUSIVE) {#ifdef ISDN_DEBUG_NET_ICALL								printk(KERN_DEBUG "n_fi: 2nd channel is down and bound\n");#endif								/* Yes, swap bindings only, if the original								 * binding is bound to channel 1 of this driver */								if ((lp->pre_device == di) &&								    (lp->pre_channel == 1)) {									isdn_net_swapbind(di);									swapped = 1;								} else {									/* ... else iterate next device */									p = (isdn_net_dev *) p->next;									continue;								}							} else {#ifdef ISDN_DEBUG_NET_ICALL								printk(KERN_DEBUG "n_fi: 2nd channel is down and unbound\n");#endif								/* No, swap always and swap excl-usage also */								isdn_net_swap_usage(idx, sidx);								isdn_net_swapbind(di);								swapped = 2;							}							/* Now check for exclusive binding again */#ifdef ISDN_DEBUG_NET_ICALL							printk(KERN_DEBUG "n_fi: final check\n");#endif							if ((dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) &&							    ((lp->pre_channel != ch) ||							     (lp->pre_device != di))) {#ifdef ISDN_DEBUG_NET_ICALL								printk(KERN_DEBUG "n_fi: final check failed\n");#endif								p = (isdn_net_dev *) p->next;								continue;							}						}					} else {						/* We are already on the second channel, so nothing to do */#ifdef ISDN_DEBUG_NET_ICALL						printk(KERN_DEBUG "n_fi: already on 2nd channel\n");#endif					}				}			}#ifdef ISDN_DEBUG_NET_ICALL			printk(KERN_DEBUG "n_fi: match2\n");#endif			n = lp->phone[0];			if (lp->flags & ISDN_NET_SECURE) {				while (n) {					if (!isdn_msncmp(nr, n->num))						break;					n = (isdn_net_phone *) n->next;				}			}			if (n || (!(lp->flags & ISDN_NET_SECURE))) {#ifdef ISDN_DEBUG_NET_ICALL				printk(KERN_DEBUG "n_fi: match3\n");#endif				/* matching interface found */				/*				 * Is the state STOPPED?				 * If so, no dialin is allowed,				 * so reject actively.				 * */				if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {					restore_flags(flags);					printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",					       lp->name);					return 3;				}				/*				 * Is the interface up?				 * If not, reject the call actively.				 */				if (!isdn_net_device_started(p)) {					restore_flags(flags);					printk(KERN_INFO "%s: incoming call, interface down -> rejected\n",					       lp->name);					return 3;				}				/* Interface is up, now see if it's a slave. If so, see if				 * it's master and parent slave is online. If not, reject the call.				 */				if (lp->master) {					isdn_net_local *mlp = (isdn_net_local *) lp->master->priv;					printk(KERN_DEBUG "ICALLslv: %s\n", lp->name);					printk(KERN_DEBUG "master=%s\n", mlp->name);					if (mlp->flags & ISDN_NET_CONNECTED) {						printk(KERN_DEBUG "master online\n");						/* Master is online, find parent-slave (master if first slave) */						while (mlp->slave) {							if ((isdn_net_local *) mlp->slave->priv == lp)								break;							mlp = (isdn_net_local *) mlp->slave->priv;						}					} else						printk(KERN_DEBUG "master offline\n");					/* Found parent, if it's offline iterate next device */					printk(KERN_DEBUG "mlpf: %d\n", mlp->flags & ISDN_NET_CONNECTED);					if (!(mlp->flags & ISDN_NET_CONNECTED)) {						p = (isdn_net_dev *) p->next;						continue;					}				} 				if (lp->flags & ISDN_NET_CALLBACK) {					int chi;					/*					 * Is the state MANUAL?					 * If so, no callback can be made,					 * so reject actively.					 * */					if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {						restore_flags(flags);						printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",						       lp->name);						return 3;					}					printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",					       lp->name, nr, eaz);					if (lp->phone[1]) {						/* Grab a free ISDN-Channel */						if ((chi = 							isdn_get_free_channel(								ISDN_USAGE_NET,								lp->l2_proto,								lp->l3_proto,							  	lp->pre_device,						 		lp->pre_channel,						 		lp->msn)								) < 0) {							printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name);							restore_flags(flags);							return 0;						}						/* Setup dialstate. */						lp->dtimer = 0;						lp->dialstate = 11;						/* Connect interface with channel */						isdn_net_bind_channel(lp, chi);#ifdef CONFIG_ISDN_PPP						if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)							if (isdn_ppp_bind(lp) < 0) {								isdn_net_unbind_channel(lp);								restore_flags(flags);								return 0;							}#endif						/* Initiate dialing by returning 2 or 4 */						restore_flags(flags);						return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4;					} else						printk(KERN_WARNING "isdn_net: %s: No phone number\n", lp->name);					restore_flags(flags);					return 0;				} else {					printk(KERN_DEBUG "%s: call from %s -> %s accepted\n", lp->name, nr,					       eaz);					/* if this interface is dialing, it does it probably on a different					   device, so free this device */					if ((lp->dialstate == 4) || (lp->dialstate == 12)) {#ifdef CONFIG_ISDN_PPP						if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)							isdn_ppp_free(lp);#endif						isdn_net_lp_disconnected(lp);						isdn_free_channel(lp->isdn_device, lp->isdn_channel,							 ISDN_USAGE_NET);					}					dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;					dev->usage[idx] |= ISDN_USAGE_NET;					strcpy(dev->num[idx], nr);					isdn_info_update();					dev->st_netdev[idx] = lp->netdev;					lp->isdn_device = di;					lp->isdn_channel = ch;					lp->ppp_slot = -1;					lp->flags |= ISDN_NET_CONNECTED;					lp->dialstate = 7;					lp->dtimer = 0;					lp->outgoing = 0;					lp->huptimer = 0;					lp->hupflags |= ISDN_WAITCHARGE;					lp->hupflags &= ~ISDN_HAVECHARGE;#ifdef CONFIG_ISDN_PPP					if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)						if (isdn_ppp_bind(lp) < 0) {							isdn_net_unbind_channel(lp);							restore_flags(flags);							return 0;						}#endif					restore_flags(flags);					return 1;				}			}		}		p = (isdn_net_dev *) p->next;	}	/* If none of configured EAZ/MSN matched and not verbose, be silent */	if (!ematch || dev->net_verbose)		printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, di, eaz);	restore_flags(flags);	return (wret == 2)?5:0;}/* * Search list of net-interfaces for an interface with given name. */isdn_net_dev *isdn_net_findif(char *name){	isdn_net_dev *p = dev->netdev;	while (p) {		if (!strcmp(p->local->name, name))			return p;		p = (isdn_net_dev *) p->next;	}	return (isdn_net_dev *) NULL;}/* * Force a net-interface to dial out. * This is called from the userlevel-routine below or * from isdn_net_start_xmit(). */intisdn_net_force_dial_lp(isdn_net_local * lp){	if ((!(lp->flags & ISDN_NET_CONNECTED)) && !lp->dialstate) {		int chi;		if (lp->phone[1]) {			ulong flags;			save_flags(flags);			cli();			/* Grab a free ISDN-Channel */			if ((chi = 						isdn_get_free_channel(							ISDN_USAGE_NET,							lp->l2_proto,							lp->l3_proto,							lp->pre_device,						 	lp->pre_channel,							lp->msn)							) < 0) {				printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name);				restore_flags(flags);				return -EAGAIN;			}			lp->dialstate = 1;			/* Connect interface with channel */			isdn_net_bind_channel(lp, chi);#ifdef CONFIG_ISDN_PPP			if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)				if (isdn_ppp_bind(lp) < 0) {					isdn_net_unbind_channel(lp);					restore_flags(flags);					return -EAGAIN;				}#endif			/* Initiate dialing */			restore_flags(flags);			isdn_net_dial();			return 0;		} else			return -EINVAL;	} else		return -EBUSY;}/* * This is called from certain upper protocol layers (multilink ppp * and x25iface encapsulation module) that want to initiate dialing * themselves. */intisdn_net_dial_req(isdn_net_local * lp){	/* is there a better error code? */	if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) return -EBUSY;	return isdn_net_force_dial_lp(lp);}/* * Force a net-interface to dial out. * This is always called from within userspace (ISDN_IOCTL_NET_DIAL). */intisdn_net_force_dial(char *name){	isdn_net_dev *p = isdn_net_findif(name);	if (!p)		return -ENODEV;	return (isdn_net_force_dial_lp(p->local));}/* * Allocate a new network-interface and initialize its data structures. */char *isdn_net_new(char *name, struct net_device *master){	isdn_net_dev *netdev;	/* Avoid creating an existing interface */	if (isdn_net_findif(name)) {		printk(KERN_WARNING "isdn_net: interface %s already exists\n", name);		return NULL;	}	if (!(netdev = (isdn_net_dev *) kmalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {		printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");		return NULL;	}	memset(netdev, 0, sizeof(isdn_net_dev));	if (!(netdev->local = (isdn_net_local *) kmalloc(sizeof(isdn_net_local), GFP_KERNEL))) {		printk(KERN_WARNING "isdn_net: Could not allocate device locals\n");		return NULL;	}	memset(netdev->local, 0, sizeof(isdn_net_local));	if (name == NULL)		strcpy(netdev->local->name, "         ");	else		strcpy(netdev->local->name, name);	strcpy(netdev->dev.name, netdev->local->name);	netdev->dev.priv = netdev->local;	netdev->dev.init = isdn_net_init;	netdev->local->p_encap = ISDN_NET_ENCAP_RAWIP;	if (master) {		/* Device shall be a slave */		struct net_device *p = (((isdn_net_local *) master->priv)->slave);		struct net_device *q = master;		netdev->local->master = master;		/* Put device at end of slave-chain */		while (p) {			q = p;			p = (((isdn_net_local *) p->priv)->slave);		}		((isdn_net_local *) q->priv)->slave = &(netdev->dev);	} else {		/* Device shall be a master */		/*		 * Watchdog timer (currently) for master only.		 */		netdev->dev.tx_timeout = isdn_net_tx_timeout;		netdev->dev.watchdog_timeo = ISDN_NET_TX_TIMEOUT;		if (register_netdev(&netdev->dev) != 0) {			printk(KERN_WARNING "isdn_net: Could not register net-device\n");			kfree(netdev->local);			kfree(netdev);			return NULL;		}	}	netdev->local->magic = ISDN_NET_MAGIC;	netdev->queue = netdev->local;	spin_lock_init(&netdev->queue_lock);	netdev->local->last = netdev->local;	netdev->local->netdev = netdev;	netdev->local->next = netdev->local;	netdev->local->tqueue.sync = 0;	netdev->local->tqueue.routine = isdn_net_softint;	netdev->local->tqueue.data = netdev->local;	spin_lock_init(&netdev->local->xmit_lock);	netdev->local->isdn_device = -1;	netdev->local->isdn_channel = -1;	netdev->local->pre_device = -1;	netdev->local->pre_channel = -1;	netdev->local->exclusive = -1;	netdev->local->ppp_slot = -1;	netdev->local->pp

⌨️ 快捷键说明

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