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

📄 isdnloop.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
 *   sdefp = pointer to struct holding ioctl parameters. * Return: *   0 on success, -E??? otherwise. */static intisdnloop_start(isdnloop_card * card, isdnloop_sdef * sdefp){	unsigned long flags;	isdnloop_sdef sdef;	int i;	if (card->flags & ISDNLOOP_FLAGS_RUNNING)		return -EBUSY;	copy_from_user((char *) &sdef, (char *) sdefp, sizeof(sdef));	save_flags(flags);	cli();	switch (sdef.ptype) {		case ISDN_PTYPE_EURO:			if (isdnloop_fake(card, "DRV1.23EC-Q.931-CAPI-CNS-BASIS-20.02.96",					  -1)) {				restore_flags(flags);				return -ENOMEM;			}			card->sil[0] = card->sil[1] = 4;			if (isdnloop_fake(card, "TEI OK", 0)) {				restore_flags(flags);				return -ENOMEM;			}			for (i = 0; i < 3; i++)				strcpy(card->s0num[i], sdef.num[i]);			break;		case ISDN_PTYPE_1TR6:			if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95",					  -1)) {				restore_flags(flags);				return -ENOMEM;			}			card->sil[0] = card->sil[1] = 4;			if (isdnloop_fake(card, "TEI OK", 0)) {				restore_flags(flags);				return -ENOMEM;			}			strcpy(card->s0num[0], sdef.num[0]);			card->s0num[1][0] = '\0';			card->s0num[2][0] = '\0';			break;		default:			restore_flags(flags);			printk(KERN_WARNING "isdnloop: Illegal D-channel protocol %d\n",			       sdef.ptype);			return -EINVAL;	}	init_timer(&card->st_timer);	card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD;	card->st_timer.function = isdnloop_polldchan;	card->st_timer.data = (unsigned long) card;	add_timer(&card->st_timer);	card->flags |= ISDNLOOP_FLAGS_RUNNING;	restore_flags(flags);	return 0;}/* * Main handler for commands sent by linklevel. */static intisdnloop_command(isdn_ctrl * c, isdnloop_card * card){	ulong a;	int i;	char cbuf[60];	isdn_ctrl cmd;	isdnloop_cdef cdef;	switch (c->command) {		case ISDN_CMD_IOCTL:			memcpy(&a, c->parm.num, sizeof(ulong));			switch (c->arg) {				case ISDNLOOP_IOCTL_DEBUGVAR:					return (ulong) card;				case ISDNLOOP_IOCTL_STARTUP:					if ((i = verify_area(VERIFY_READ, (void *) a, sizeof(isdnloop_sdef))))						return i;					return (isdnloop_start(card, (isdnloop_sdef *) a));					break;				case ISDNLOOP_IOCTL_ADDCARD:					if ((i = verify_area(VERIFY_READ, (void *) a, sizeof(isdnloop_cdef))))						return i;					copy_from_user((char *) &cdef, (char *) a, sizeof(cdef));					return (isdnloop_addcard(cdef.id1));					break;				case ISDNLOOP_IOCTL_LEASEDCFG:					if (a) {						if (!card->leased) {							card->leased = 1;							while (card->ptype == ISDN_PTYPE_UNKNOWN) {								schedule_timeout(10);							}							schedule_timeout(10);							sprintf(cbuf, "00;FV2ON\n01;EAZ1\n02;EAZ2\n");							i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);							printk(KERN_INFO							       "isdnloop: (%s) Leased-line mode enabled\n",							       CID);							cmd.command = ISDN_STAT_RUN;							cmd.driver = card->myid;							cmd.arg = 0;							card->interface.statcallb(&cmd);						}					} else {						if (card->leased) {							card->leased = 0;							sprintf(cbuf, "00;FV2OFF\n");							i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);							printk(KERN_INFO							       "isdnloop: (%s) Leased-line mode disabled\n",							       CID);							cmd.command = ISDN_STAT_RUN;							cmd.driver = card->myid;							cmd.arg = 0;							card->interface.statcallb(&cmd);						}					}					return 0;				default:					return -EINVAL;			}			break;		case ISDN_CMD_DIAL:			if (!card->flags & ISDNLOOP_FLAGS_RUNNING)				return -ENODEV;			if (card->leased)				break;			if ((c->arg & 255) < ISDNLOOP_BCH) {				char *p;				char dial[50];				char dcode[4];				a = c->arg;				p = c->parm.setup.phone;				if (*p == 's' || *p == 'S') {					/* Dial for SPV */					p++;					strcpy(dcode, "SCA");				} else					/* Normal Dial */					strcpy(dcode, "CAL");				strcpy(dial, p);				sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),					dcode, dial, c->parm.setup.si1,				c->parm.setup.si2, c->parm.setup.eazmsn);				i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);			}			break;		case ISDN_CMD_ACCEPTD:			if (!card->flags & ISDNLOOP_FLAGS_RUNNING)				return -ENODEV;			if (c->arg < ISDNLOOP_BCH) {				a = c->arg + 1;				cbuf[0] = 0;				switch (card->l2_proto[a - 1]) {					case ISDN_PROTO_L2_X75I:						sprintf(cbuf, "%02d;BX75\n", (int) a);						break;#ifdef CONFIG_ISDN_X25					case ISDN_PROTO_L2_X25DTE:						sprintf(cbuf, "%02d;BX2T\n", (int) a);						break;					case ISDN_PROTO_L2_X25DCE:						sprintf(cbuf, "%02d;BX2C\n", (int) a);						break;#endif					case ISDN_PROTO_L2_HDLC:						sprintf(cbuf, "%02d;BTRA\n", (int) a);						break;				}				if (strlen(cbuf))					i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);				sprintf(cbuf, "%02d;DCON_R\n", (int) a);				i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);			}			break;		case ISDN_CMD_ACCEPTB:			if (!card->flags & ISDNLOOP_FLAGS_RUNNING)				return -ENODEV;			if (c->arg < ISDNLOOP_BCH) {				a = c->arg + 1;				switch (card->l2_proto[a - 1]) {					case ISDN_PROTO_L2_X75I:						sprintf(cbuf, "%02d;BCON_R,BX75\n", (int) a);						break;#ifdef CONFIG_ISDN_X25					case ISDN_PROTO_L2_X25DTE:						sprintf(cbuf, "%02d;BCON_R,BX2T\n", (int) a);						break;					case ISDN_PROTO_L2_X25DCE:						sprintf(cbuf, "%02d;BCON_R,BX2C\n", (int) a);						break;#endif					case ISDN_PROTO_L2_HDLC:						sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int) a);						break;					default:						sprintf(cbuf, "%02d;BCON_R\n", (int) a);				}				printk(KERN_DEBUG "isdnloop writecmd '%s'\n", cbuf);				i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);				break;		case ISDN_CMD_HANGUP:				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)					return -ENODEV;				if (c->arg < ISDNLOOP_BCH) {					a = c->arg + 1;					sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a);					i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);				}				break;		case ISDN_CMD_SETEAZ:				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)					return -ENODEV;				if (card->leased)					break;				if (c->arg < ISDNLOOP_BCH) {					a = c->arg + 1;					if (card->ptype == ISDN_PTYPE_EURO) {						sprintf(cbuf, "%02d;MS%s%s\n", (int) a,							c->parm.num[0] ? "N" : "ALL", c->parm.num);					} else						sprintf(cbuf, "%02d;EAZ%s\n", (int) a,							c->parm.num[0] ? c->parm.num : (u_char *) "0123456789");					i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);				}				break;		case ISDN_CMD_CLREAZ:				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)					return -ENODEV;				if (card->leased)					break;				if (c->arg < ISDNLOOP_BCH) {					a = c->arg + 1;					if (card->ptype == ISDN_PTYPE_EURO)						sprintf(cbuf, "%02d;MSNC\n", (int) a);					else						sprintf(cbuf, "%02d;EAZC\n", (int) a);					i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);				}				break;		case ISDN_CMD_SETL2:				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)					return -ENODEV;				if ((c->arg & 255) < ISDNLOOP_BCH) {					a = c->arg;					switch (a >> 8) {						case ISDN_PROTO_L2_X75I:							sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1);							break;#ifdef CONFIG_ISDN_X25						case ISDN_PROTO_L2_X25DTE:							sprintf(cbuf, "%02d;BX2T\n", (int) (a & 255) + 1);							break;						case ISDN_PROTO_L2_X25DCE:							sprintf(cbuf, "%02d;BX2C\n", (int) (a & 255) + 1);							break;#endif						case ISDN_PROTO_L2_HDLC:							sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1);							break;						default:							return -EINVAL;					}					i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);					card->l2_proto[a & 255] = (a >> 8);				}				break;		case ISDN_CMD_GETL2:				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)					return -ENODEV;				if ((c->arg & 255) < ISDNLOOP_BCH)					return card->l2_proto[c->arg & 255];				else					return -ENODEV;		case ISDN_CMD_SETL3:				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)					return -ENODEV;				return 0;		case ISDN_CMD_GETL3:				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)					return -ENODEV;				if ((c->arg & 255) < ISDNLOOP_BCH)					return ISDN_PROTO_L3_TRANS;				else					return -ENODEV;		case ISDN_CMD_GETEAZ:				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)					return -ENODEV;				break;		case ISDN_CMD_SETSIL:				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)					return -ENODEV;				break;		case ISDN_CMD_GETSIL:				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)					return -ENODEV;				break;		case ISDN_CMD_LOCK:				MOD_INC_USE_COUNT;				break;		case ISDN_CMD_UNLOCK:				MOD_DEC_USE_COUNT;				break;		default:				return -EINVAL;			}	}	return 0;}/* * Find card with given driverId */static inline isdnloop_card *isdnloop_findcard(int driverid){	isdnloop_card *p = cards;	while (p) {		if (p->myid == driverid)			return p;		p = p->next;	}	return (isdnloop_card *) 0;}/* * Wrapper functions for interface to linklevel */static intif_command(isdn_ctrl * c){	isdnloop_card *card = isdnloop_findcard(c->driver);	if (card)		return (isdnloop_command(c, card));	printk(KERN_ERR	       "isdnloop: if_command called with invalid driverId!\n");	return -ENODEV;}static intif_writecmd(const u_char * buf, int len, int user, int id, int channel){	isdnloop_card *card = isdnloop_findcard(id);	if (card) {		if (!card->flags & ISDNLOOP_FLAGS_RUNNING)			return -ENODEV;		return (isdnloop_writecmd(buf, len, user, card));	}	printk(KERN_ERR	       "isdnloop: if_writecmd called with invalid driverId!\n");	return -ENODEV;}static intif_readstatus(u_char * buf, int len, int user, int id, int channel){	isdnloop_card *card = isdnloop_findcard(id);	if (card) {		if (!card->flags & ISDNLOOP_FLAGS_RUNNING)			return -ENODEV;		return (isdnloop_readstatus(buf, len, user, card));	}	printk(KERN_ERR	       "isdnloop: if_readstatus called with invalid driverId!\n");	return -ENODEV;}static intif_sendbuf(int id, int channel, int ack, struct sk_buff *skb){	isdnloop_card *card = isdnloop_findcard(id);	if (card) {		if (!card->flags & ISDNLOOP_FLAGS_RUNNING)			return -ENODEV;		/* ack request stored in skb scratch area */		*(skb->head) = ack;		return (isdnloop_sendbuf(channel, skb, card));	}	printk(KERN_ERR	       "isdnloop: if_sendbuf called with invalid driverId!\n");	return -ENODEV;}/* * Allocate a new card-struct, initialize it * link it into cards-list and register it at linklevel. */static isdnloop_card *isdnloop_initcard(char *id){	isdnloop_card *card;	int i;	if (!(card = (isdnloop_card *) kmalloc(sizeof(isdnloop_card), GFP_KERNEL))) {		printk(KERN_WARNING		 "isdnloop: (%s) Could not allocate card-struct.\n", id);		return (isdnloop_card *) 0;	}	memset((char *) card, 0, sizeof(isdnloop_card));	card->interface.channels = ISDNLOOP_BCH;	card->interface.hl_hdrlen  = 1; /* scratch area for storing ack flag*/ 	card->interface.maxbufsize = 4000;	card->interface.command = if_command;	card->interface.writebuf_skb = if_sendbuf;	card->interface.writecmd = if_writecmd;	card->interface.readstat = if_readstatus;	card->interface.features = ISDN_FEATURE_L2_X75I |#ifdef CONFIG_ISDN_X25	    ISDN_FEATURE_L2_X25DTE |	    ISDN_FEATURE_L2_X25DCE |#endif	    ISDN_FEATURE_L2_HDLC |	    ISDN_FEATURE_L3_TRANS |	    ISDN_FEATURE_P_UNKNOWN;	card->ptype = ISDN_PTYPE_UNKNOWN;	strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);	card->msg_buf_write = card->msg_buf;	card->msg_buf_read = card->msg_buf;	card->msg_buf_end = &card->msg_buf[sizeof(card->msg_buf) - 1];	for (i = 0; i < ISDNLOOP_BCH; i++) {		card->l2_proto[i] = ISDN_PROTO_L2_X75I;		skb_queue_head_init(&card->bqueue[i]);	}	skb_queue_head_init(&card->dqueue);	card->next = cards;	cards = card;	if (!register_isdn(&card->interface)) {		cards = cards->next;		printk(KERN_WARNING		       "isdnloop: Unable to register %s\n", id);		kfree(card);		return (isdnloop_card *) 0;	}	card->myid = card->interface.channels;	return card;}static intisdnloop_addcard(char *id1){	ulong flags;	isdnloop_card *card;	save_flags(flags);	cli();	if (!(card = isdnloop_initcard(id1))) {		restore_flags(flags);		return -EIO;	}	restore_flags(flags);	printk(KERN_INFO	       "isdnloop: (%s) virtual card added\n",	       card->interface.id);	return 0;}#ifdef MODULE#define isdnloop_init init_module#elsevoidisdnloop_setup(char *str, int *ints){	static char sid[20];	if (strlen(str)) {		strcpy(sid, str);		isdnloop_id = sid;	}}#endifintisdnloop_init(void){	char *p;	char rev[10];	/* No symbols to export, hide all symbols */	EXPORT_NO_SYMBOLS;	if ((p = strchr(revision, ':'))) {		strcpy(rev, p + 1);		p = strchr(rev, '$');		*p = 0;	} else		strcpy(rev, " ??? ");	printk(KERN_NOTICE "isdnloop-ISDN-driver Rev%s\n", rev);	return (isdnloop_addcard(isdnloop_id));}#ifdef MODULEvoidcleanup_module(void){	isdn_ctrl cmd;	isdnloop_card *card = cards;	isdnloop_card *last;	int i;	isdnloop_stopallcards();	while (card) {		cmd.command = ISDN_STAT_UNLOAD;		cmd.driver = card->myid;		card->interface.statcallb(&cmd);		for (i = 0; i < ISDNLOOP_BCH; i++)			isdnloop_free_queue(card, i);		card = card->next;	}	card = cards;	while (card) {		struct sk_buff *skb;		last = card;		while ((skb = skb_dequeue(&card->dqueue)))			dev_kfree_skb(skb);		card = card->next;		kfree(last);	}	printk(KERN_NOTICE "isdnloop-ISDN-driver unloaded\n");}#endif

⌨️ 快捷键说明

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