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

📄 isdn_common.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 4 页
字号:
		if (((!usage) || ((dev->usage[i] & ISDN_USAGE_MASK) == usage)) &&		    (dev->drvmap[i] == di) &&		    (dev->chanmap[i] == ch)) {			dev->usage[i] &= (ISDN_USAGE_NONE | ISDN_USAGE_EXCLUSIVE);			strcpy(dev->num[i], "???");			dev->ibytes[i] = 0;			dev->obytes[i] = 0;// 20.10.99 JIM, try to reinitialize v110 !			dev->v110emu[i] = 0;			atomic_set(&(dev->v110use[i]), 0);			isdn_v110_close(dev->v110[i]);			dev->v110[i] = NULL;// 20.10.99 JIM, try to reinitialize v110 !			isdn_info_update();			isdn_free_queue(&dev->drv[di]->rpqueue[ch]);		}	restore_flags(flags);}/* * Cancel Exclusive-Flag for ISDN-channel */voidisdn_unexclusive_channel(int di, int ch){	int i;	ulong flags;	save_flags(flags);	cli();	for (i = 0; i < ISDN_MAX_CHANNELS; i++)		if ((dev->drvmap[i] == di) &&		    (dev->chanmap[i] == ch)) {			dev->usage[i] &= ~ISDN_USAGE_EXCLUSIVE;			isdn_info_update();			restore_flags(flags);			return;		}	restore_flags(flags);}/* *  writebuf replacement for SKB_ABLE drivers */static intisdn_writebuf_stub(int drvidx, int chan, const u_char * buf, int len,		   int user){	int ret;	int hl = dev->drv[drvidx]->interface->hl_hdrlen;	struct sk_buff *skb = alloc_skb(hl + len, GFP_ATOMIC);	if (!skb)		return 0;	skb_reserve(skb, hl);	if (user)		copy_from_user(skb_put(skb, len), buf, len);	else		memcpy(skb_put(skb, len), buf, len);	ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb);	if (ret <= 0)		dev_kfree_skb(skb);	if (ret > 0)		dev->obytes[isdn_dc2minor(drvidx, chan)] += ret;	return ret;}/* * Return: length of data on success, -ERRcode on failure. */intisdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb){	int ret;	struct sk_buff *nskb = NULL;	int v110_ret = skb->len;	int idx = isdn_dc2minor(drvidx, chan);	if (dev->v110[idx]) {		atomic_inc(&dev->v110use[idx]);		nskb = isdn_v110_encode(dev->v110[idx], skb);		atomic_dec(&dev->v110use[idx]);		if (!nskb)			return 0;		v110_ret = *((int *)nskb->data);		skb_pull(nskb, sizeof(int));		if (!nskb->len) {			dev_kfree_skb(nskb);			return v110_ret;		}		/* V.110 must always be acknowledged */		ack = 1;		ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, nskb);	} else {		int hl = dev->drv[drvidx]->interface->hl_hdrlen;		if( skb_headroom(skb) < hl ){			/* 			 * This should only occur when new HL driver with			 * increased hl_hdrlen was loaded after netdevice			 * was created and connected to the new driver.			 *			 * The V.110 branch (re-allocates on its own) does			 * not need this			 */			struct sk_buff * skb_tmp;			skb_tmp = skb_realloc_headroom(skb, hl);			printk(KERN_DEBUG "isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp ? "" : " failed");			if (!skb_tmp) return -ENOMEM; /* 0 better? */			ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb_tmp);			if( ret > 0 ){				dev_kfree_skb(skb);			} else {				dev_kfree_skb(skb_tmp);			}		} else {			ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb);		}	}	if (ret > 0) {		dev->obytes[idx] += ret;		if (dev->v110[idx]) {			atomic_inc(&dev->v110use[idx]);			dev->v110[idx]->skbuser++;			atomic_dec(&dev->v110use[idx]);			/* For V.110 return unencoded data length */			ret = v110_ret;			/* if the complete frame was send we free the skb;			   if not upper function will requeue the skb */ 			if (ret == skb->len)				dev_kfree_skb(skb);		}	} else		if (dev->v110[idx])			dev_kfree_skb(nskb);	return ret;}intregister_isdn_module(isdn_module *m) {	return 0;}intunregister_isdn_module(isdn_module *m) {	return 0;}intisdn_add_channels(driver *d, int drvidx, int n, int adding){	int j, k, m;	ulong flags;	init_waitqueue_head(&d->st_waitq);	if (d->flags & DRV_FLAG_RUNNING)		return -1;       	if (n < 1) return 0;	m = (adding) ? d->channels + n : n;	if (dev->channels + n > ISDN_MAX_CHANNELS) {		printk(KERN_WARNING "register_isdn: Max. %d channels supported\n",		       ISDN_MAX_CHANNELS);		return -1;	}	if ((adding) && (d->rcverr))		kfree(d->rcverr);	if (!(d->rcverr = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) {		printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");		return -1;	}	memset((char *) d->rcverr, 0, sizeof(int) * m);	if ((adding) && (d->rcvcount))		kfree(d->rcvcount);	if (!(d->rcvcount = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) {		printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");		if (!adding) kfree(d->rcverr);		return -1;	}	memset((char *) d->rcvcount, 0, sizeof(int) * m);	if ((adding) && (d->rpqueue)) {		for (j = 0; j < d->channels; j++)			isdn_free_queue(&d->rpqueue[j]);		kfree(d->rpqueue);	}	if (!(d->rpqueue =	      (struct sk_buff_head *) kmalloc(sizeof(struct sk_buff_head) * m, GFP_KERNEL))) {		printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");		if (!adding) {			kfree(d->rcvcount);			kfree(d->rcverr);		}		return -1; 	}	for (j = 0; j < m; j++) {		skb_queue_head_init(&d->rpqueue[j]);	}	if ((adding) && (d->rcv_waitq))		kfree(d->rcv_waitq);	d->rcv_waitq = (wait_queue_head_t *)		kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL);	if (!d->rcv_waitq) {		printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");		if (!adding) {			kfree(d->rpqueue);			kfree(d->rcvcount);			kfree(d->rcverr);		}		return -1;	}	d->snd_waitq = d->rcv_waitq + m;	for (j = 0; j < m; j++) {		init_waitqueue_head(&d->rcv_waitq[j]);		init_waitqueue_head(&d->snd_waitq[j]);	}	dev->channels += n;	save_flags(flags);	cli();	for (j = d->channels; j < m; j++)		for (k = 0; k < ISDN_MAX_CHANNELS; k++)			if (dev->chanmap[k] < 0) {				dev->chanmap[k] = j;				dev->drvmap[k] = drvidx;				isdn_register_devfs(k);				break;			}	restore_flags(flags);	d->channels = m;	return 0;}/* * Low-level-driver registration */static voidset_global_features(void){	int drvidx;	dev->global_features = 0;	for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) {		if (!dev->drv[drvidx])			continue;		if (dev->drv[drvidx]->interface)			dev->global_features |= dev->drv[drvidx]->interface->features;	}}#ifdef CONFIG_ISDN_DIVERSIONstatic char *map_drvname(int di){  if ((di < 0) || (di >= ISDN_MAX_DRIVERS))     return(NULL);  return(dev->drvid[di]); /* driver name */} /* map_drvname */static int map_namedrv(char *id){  int i;   for (i = 0; i < ISDN_MAX_DRIVERS; i++)    { if (!strcmp(dev->drvid[i],id))         return(i);    }   return(-1);} /* map_namedrv */int DIVERT_REG_NAME(isdn_divert_if *i_div){  if (i_div->if_magic != DIVERT_IF_MAGIC)     return(DIVERT_VER_ERR);  switch (i_div->cmd)    {      case DIVERT_CMD_REL:        if (divert_if != i_div)           return(DIVERT_REL_ERR);        divert_if = NULL; /* free interface */        MOD_DEC_USE_COUNT;        return(DIVERT_NO_ERR);      case DIVERT_CMD_REG:        if (divert_if)           return(DIVERT_REG_ERR);        i_div->ll_cmd = isdn_command; /* set command function */        i_div->drv_to_name = map_drvname;         i_div->name_to_drv = map_namedrv;         MOD_INC_USE_COUNT;        divert_if = i_div; /* remember interface */        return(DIVERT_NO_ERR);      default:        return(DIVERT_CMD_ERR);       }} /* DIVERT_REG_NAME */EXPORT_SYMBOL(DIVERT_REG_NAME);#endif CONFIG_ISDN_DIVERSIONEXPORT_SYMBOL(register_isdn);EXPORT_SYMBOL(register_isdn_module);EXPORT_SYMBOL(unregister_isdn_module);#ifdef CONFIG_ISDN_PPPEXPORT_SYMBOL(isdn_ppp_register_compressor);EXPORT_SYMBOL(isdn_ppp_unregister_compressor);#endifintregister_isdn(isdn_if * i){	driver *d;	int j;	ulong flags;	int drvidx;	if (dev->drivers >= ISDN_MAX_DRIVERS) {		printk(KERN_WARNING "register_isdn: Max. %d drivers supported\n",		       ISDN_MAX_DRIVERS);		return 0;	}	if (!i->writebuf_skb) {		printk(KERN_WARNING "register_isdn: No write routine given.\n");		return 0;	}	if (!(d = (driver *) kmalloc(sizeof(driver), GFP_KERNEL))) {		printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n");		return 0;	}	memset((char *) d, 0, sizeof(driver));	d->maxbufsize = i->maxbufsize;	d->pktcount = 0;	d->stavail = 0;	d->flags = DRV_FLAG_LOADED;	d->online = 0;	d->interface = i;	d->channels = 0;	for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)		if (!dev->drv[drvidx])			break;	if (isdn_add_channels(d, drvidx, i->channels, 0)) {		kfree(d);		return 0;	}	i->channels = drvidx;	i->rcvcallb_skb = isdn_receive_skb_callback;	i->statcallb = isdn_status_callback;	if (!strlen(i->id))		sprintf(i->id, "line%d", drvidx);	save_flags(flags);	cli();	for (j = 0; j < drvidx; j++)		if (!strcmp(i->id, dev->drvid[j]))			sprintf(i->id, "line%d", drvidx);	dev->drv[drvidx] = d;	strcpy(dev->drvid[drvidx], i->id);	isdn_info_update();	dev->drivers++;	set_global_features();	restore_flags(flags);	return 1;}/* ***************************************************************************** * And now the modules code. ***************************************************************************** */extern int printk(const char *fmt,...);#ifdef MODULE#define isdn_init init_module#endifstatic char *isdn_getrev(const char *revision){	char *rev;	char *p;	if ((p = strchr(revision, ':'))) {		rev = p + 2;		p = strchr(rev, '$');		*--p = 0;	} else		rev = "???";	return rev;}#ifdef CONFIG_DEVFS_FSstatic devfs_handle_t devfs_handle;static void isdn_register_devfs(int k){	char buf[11];	sprintf (buf, "isdn%d", k);	dev->devfs_handle_isdnX[k] =	    devfs_register (devfs_handle, buf, DEVFS_FL_DEFAULT,			    ISDN_MAJOR, ISDN_MINOR_B + k,0600 | S_IFCHR,			    &isdn_fops, NULL);	sprintf (buf, "isdnctrl%d", k);	dev->devfs_handle_isdnctrlX[k] =	    devfs_register (devfs_handle, buf, DEVFS_FL_DEFAULT,			    ISDN_MAJOR, ISDN_MINOR_CTRL + k, 0600 | S_IFCHR,			    &isdn_fops, NULL);}static void isdn_unregister_devfs(int k){	devfs_unregister (dev->devfs_handle_isdnX[k]);	devfs_unregister (dev->devfs_handle_isdnctrlX[k]);}static void isdn_init_devfs(void){#  ifdef CONFIG_ISDN_PPP	int i;#  endif	devfs_handle = devfs_mk_dir (NULL, "isdn", NULL);#  ifdef CONFIG_ISDN_PPP	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {		char buf[8];		sprintf (buf, "ippp%d", i);		dev->devfs_handle_ipppX[i] =		    devfs_register (devfs_handle, buf, DEVFS_FL_DEFAULT,				    ISDN_MAJOR, ISDN_MINOR_PPP + i,				    0600 | S_IFCHR, &isdn_fops, NULL);	}#  endif	dev->devfs_handle_isdninfo =	    devfs_register (devfs_handle, "isdninfo", DEVFS_FL_DEFAULT,			    ISDN_MAJOR, ISDN_MINOR_STATUS, 0600 | S_IFCHR,			    &isdn_fops, NULL);	dev->devfs_handle_isdnctrl =	    devfs_register (devfs_handle, "isdnctrl", DEVFS_FL_DEFAULT,			    ISDN_MAJOR, ISDN_MINOR_CTRL, 0600 | S_IFCHR, 			    &isdn_fops, NULL);}static void isdn_cleanup_devfs(void){#  ifdef CONFIG_ISDN_PPP	int i;	for (i = 0; i < ISDN_MAX_CHANNELS; i++) 		devfs_unregister (dev->devfs_handle_ipppX[i]);#  endif	devfs_unregister (dev->devfs_handle_isdninfo);	devfs_unregister (dev->devfs_handle_isdnctrl);	devfs_unregister (devfs_handle);}#else   /* CONFIG_DEVFS_FS */static void isdn_register_devfs(int dummy){	return;}static void isdn_unregister_devfs(int dummy){	return;}static void isdn_init_devfs(void){    return;}static void isdn_cleanup_devfs(void){    return;}#endif  /* CONFIG_DEVFS_FS *//* * Allocate and initialize all data, register modem-devices */intisdn_init(void){	int i;	char tmprev[50];	if (!(dev = (isdn_dev *) vmalloc(sizeof(isdn_dev)))) {		printk(KERN_WARNING "isdn: Could not allocate device-struct.\n");		return -EIO;	}	memset((char *) dev, 0, sizeof(isdn_dev));	init_timer(&dev->timer);	dev->timer.function = isdn_timer_funct;	init_MUTEX(&dev->sem);	init_waitqueue_head(&dev->info_waitq);	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {		dev->drvmap[i] = -1;		dev->chanmap[i] = -1;		dev->m_idx[i] = -1;		strcpy(dev->num[i], "???");		init_waitqueue_head(&dev->mdm.info[i].open_wait);		init_waitqueue_head(&dev->mdm.info[i].close_wait);	}	if (devfs_register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) {		printk(KERN_WARNING "isdn: Could not register control devices\n");		vfree(dev);		return -EIO;	}	isdn_init_devfs();	if ((i = isdn_tty_modem_init()) < 0) {		printk(KERN_WARNING "isdn: Could not register tty devices\n");		if (i == -3)			tty_unregister_driver(&dev->mdm.cua_modem);		if (i <= -2)			tty_unregister_driver(&dev->mdm.tty_modem);		vfree(dev);		isdn_cleanup_devfs();		devfs_unregister_chrdev(ISDN_MAJOR, "isdn");		return -EIO;	}#ifdef CONFIG_ISDN_PPP	if (isdn_ppp_init() < 0) {		printk(KERN_WARNING "isdn: Could not create PPP-device-structs\n");		tty_unregister_driver(&dev->mdm.tty_modem);		tty_unregister_driver(&dev->mdm.cua_modem);		for (i = 0; i < ISDN_MAX_CHANNELS; i++)			kfree(dev->mdm.info[i].xmit_buf - 4);		isdn_cleanup_devfs();		devfs_unregister_chrdev(ISDN_MAJOR, "isdn");		vfree(dev);		return -EIO;	}#endif                          /* CONFIG_ISDN_PPP */	strcpy(tmprev, isdn_revision);	printk(KERN_NOTICE "ISDN subsystem Rev: %s/", isdn_getrev(tmprev));	strcpy(tmprev, isdn_tty_revision);	printk("%s/", isdn_getrev(tmprev));	strcpy(tmprev, isdn_net_revision);	printk("%s/", isdn_getrev(tmprev));	strcpy(tmprev, isdn_ppp_revision);	printk("%s/", isdn_getrev(tmprev));	strcpy(tmprev, isdn_audio_revision);	printk("%s/", isdn_getrev(tmprev));	strcpy(tmprev, isdn_v110_revision);	printk("%s", isdn_getrev(tmprev));#ifdef MODULE	printk(" loaded\n");#else	printk("\n");	isdn_cards_init();#endif	isdn_info_update();	return 0;}#ifdef MODULE/* * Unload module */voidcleanup_module(void){	int flags;	int i;#ifdef CONFIG_ISDN_PPP	isdn_ppp_cleanup();#endif	save_flags(flags);	cli();	if (isdn_net_rmall() < 0) {		printk(KERN_WARNING "isdn: net-device busy, remove cancelled\n");		restore_flags(flags);		return;	}	if (tty_unregister_driver(&dev->mdm.tty_modem)) {		printk(KERN_WARNING "isdn: ttyI-device busy, remove cancelled\n");		restore_flags(flags);		return;	}	if (tty_unregister_driver(&dev->mdm.cua_modem)) {		printk(KERN_WARNING "isdn: cui-device busy, remove cancelled\n");		restore_flags(flags);		return;	}	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {		isdn_tty_cleanup_xmit(&dev->mdm.info[i]);		kfree(dev->mdm.info[i].xmit_buf - 4);#ifdef CONFIG_ISDN_TTY_FAX		kfree(dev->mdm.info[i].fax);#endif	}	if (devfs_unregister_chrdev(ISDN_MAJOR, "isdn") != 0) {		printk(KERN_WARNING "isdn: controldevice busy, remove cancelled\n");		restore_flags(flags);	} else {		isdn_cleanup_devfs();		del_timer(&dev->timer);		restore_flags(flags);		/* call vfree with interrupts enabled, else it will hang */		vfree(dev);		printk(KERN_NOTICE "ISDN-subsystem unloaded\n");	}}#endif

⌨️ 快捷键说明

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