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

📄 icn.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
icn_disable_cards(void){	icn_card *card = cards;	while (card) {		if (!request_region(card->port, ICN_PORTLEN, "icn-isdn")) {			printk(KERN_WARNING			       "icn: (%s) ports 0x%03x-0x%03x in use.\n",			       CID,			       card->port,			       card->port + ICN_PORTLEN);		} else {			OUTB_P(0, ICN_RUN);	/* Reset Controller     */			OUTB_P(0, ICN_MAPRAM);	/* Disable RAM          */			release_region(card->port, ICN_PORTLEN);		}		card = card->next;	}}static inticn_command(isdn_ctrl * c, icn_card * card){	ulong a;	ulong flags;	int i;	char cbuf[60];	isdn_ctrl cmd;	icn_cdef cdef;	char __user *arg;	switch (c->command) {		case ISDN_CMD_IOCTL:			memcpy(&a, c->parm.num, sizeof(ulong));			arg = (char __user *)a;			switch (c->arg) {				case ICN_IOCTL_SETMMIO:					if (dev.memaddr != (a & 0x0ffc000)) {						if (!request_mem_region(a & 0x0ffc000, 0x4000, "icn-isdn (all cards)")) {							printk(KERN_WARNING							       "icn: memory at 0x%08lx in use.\n",							       a & 0x0ffc000);							return -EINVAL;						}						release_mem_region(a & 0x0ffc000, 0x4000);						icn_stopallcards();						spin_lock_irqsave(&card->lock, flags);						if (dev.mvalid) {							iounmap(dev.shmem);							release_mem_region(dev.memaddr, 0x4000);						}						dev.mvalid = 0;						dev.memaddr = a & 0x0ffc000;						spin_unlock_irqrestore(&card->lock, flags);						printk(KERN_INFO						       "icn: (%s) mmio set to 0x%08lx\n",						       CID,						       dev.memaddr);					}					break;				case ICN_IOCTL_GETMMIO:					return (long) dev.memaddr;				case ICN_IOCTL_SETPORT:					if (a == 0x300 || a == 0x310 || a == 0x320 || a == 0x330					    || a == 0x340 || a == 0x350 || a == 0x360 ||					    a == 0x308 || a == 0x318 || a == 0x328 || a == 0x338					    || a == 0x348 || a == 0x358 || a == 0x368) {						if (card->port != (unsigned short) a) {							if (!request_region((unsigned short) a, ICN_PORTLEN, "icn-isdn")) {								printk(KERN_WARNING								       "icn: (%s) ports 0x%03x-0x%03x in use.\n",								       CID, (int) a, (int) a + ICN_PORTLEN);								return -EINVAL;							}							release_region((unsigned short) a, ICN_PORTLEN);							icn_stopcard(card);							spin_lock_irqsave(&card->lock, flags);							if (card->rvalid)								release_region(card->port, ICN_PORTLEN);							card->port = (unsigned short) a;							card->rvalid = 0;							if (card->doubleS0) {								card->other->port = (unsigned short) a;								card->other->rvalid = 0;							}							spin_unlock_irqrestore(&card->lock, flags);							printk(KERN_INFO							       "icn: (%s) port set to 0x%03x\n",							CID, card->port);						}					} else						return -EINVAL;					break;				case ICN_IOCTL_GETPORT:					return (int) card->port;				case ICN_IOCTL_GETDOUBLE:					return (int) card->doubleS0;				case ICN_IOCTL_DEBUGVAR:					if (copy_to_user(arg,							 &card,							 sizeof(ulong)))						return -EFAULT;					a += sizeof(ulong);					{						ulong l = (ulong) & dev;						if (copy_to_user(arg,								 &l,								 sizeof(ulong)))							return -EFAULT;					}					return 0;				case ICN_IOCTL_LOADBOOT:					if (dev.firstload) {						icn_disable_cards();						dev.firstload = 0;					}					icn_stopcard(card);					return (icn_loadboot(arg, card));				case ICN_IOCTL_LOADPROTO:					icn_stopcard(card);					if ((i = (icn_loadproto(arg, card))))						return i;					if (card->doubleS0)						i = icn_loadproto(arg + ICN_CODE_STAGE2, card->other);					return i;					break;				case ICN_IOCTL_ADDCARD:					if (!dev.firstload)						return -EBUSY;					if (copy_from_user(&cdef,							   arg,							   sizeof(cdef)))						return -EFAULT;					return (icn_addcard(cdef.port, cdef.id1, cdef.id2));					break;				case ICN_IOCTL_LEASEDCFG:					if (a) {						if (!card->leased) {							card->leased = 1;							while (card->ptype == ISDN_PTYPE_UNKNOWN) {								msleep_interruptible(ICN_BOOT_TIMEOUT1);							}							msleep_interruptible(ICN_BOOT_TIMEOUT1);							sprintf(cbuf, "00;FV2ON\n01;EAZ%c\n02;EAZ%c\n",								(a & 1)?'1':'C', (a & 2)?'2':'C');							i = icn_writecmd(cbuf, strlen(cbuf), 0, card);							printk(KERN_INFO							       "icn: (%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 = icn_writecmd(cbuf, strlen(cbuf), 0, card);							printk(KERN_INFO							       "icn: (%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 & ICN_FLAGS_RUNNING)				return -ENODEV;			if (card->leased)				break;			if ((c->arg & 255) < ICN_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 = icn_writecmd(cbuf, strlen(cbuf), 0, card);			}			break;		case ISDN_CMD_ACCEPTD:			if (!card->flags & ICN_FLAGS_RUNNING)				return -ENODEV;			if (c->arg < ICN_BCH) {				a = c->arg + 1;				if (card->fw_rev >= 300) {					switch (card->l2_proto[a - 1]) {						case ISDN_PROTO_L2_X75I:							sprintf(cbuf, "%02d;BX75\n", (int) a);							break;						case ISDN_PROTO_L2_HDLC:							sprintf(cbuf, "%02d;BTRA\n", (int) a);							break;					}					i = icn_writecmd(cbuf, strlen(cbuf), 0, card);				}				sprintf(cbuf, "%02d;DCON_R\n", (int) a);				i = icn_writecmd(cbuf, strlen(cbuf), 0, card);			}			break;		case ISDN_CMD_ACCEPTB:			if (!card->flags & ICN_FLAGS_RUNNING)				return -ENODEV;			if (c->arg < ICN_BCH) {				a = c->arg + 1;				if (card->fw_rev >= 300)					switch (card->l2_proto[a - 1]) {						case ISDN_PROTO_L2_X75I:							sprintf(cbuf, "%02d;BCON_R,BX75\n", (int) a);							break;						case ISDN_PROTO_L2_HDLC:							sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int) a);							break;				} else					sprintf(cbuf, "%02d;BCON_R\n", (int) a);				i = icn_writecmd(cbuf, strlen(cbuf), 0, card);			}			break;		case ISDN_CMD_HANGUP:			if (!card->flags & ICN_FLAGS_RUNNING)				return -ENODEV;			if (c->arg < ICN_BCH) {				a = c->arg + 1;				sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a);				i = icn_writecmd(cbuf, strlen(cbuf), 0, card);			}			break;		case ISDN_CMD_SETEAZ:			if (!card->flags & ICN_FLAGS_RUNNING)				return -ENODEV;			if (card->leased)				break;			if (c->arg < ICN_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] ? (char *)(c->parm.num) : "0123456789");				i = icn_writecmd(cbuf, strlen(cbuf), 0, card);			}			break;		case ISDN_CMD_CLREAZ:			if (!card->flags & ICN_FLAGS_RUNNING)				return -ENODEV;			if (card->leased)				break;			if (c->arg < ICN_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 = icn_writecmd(cbuf, strlen(cbuf), 0, card);			}			break;		case ISDN_CMD_SETL2:			if (!card->flags & ICN_FLAGS_RUNNING)				return -ENODEV;			if ((c->arg & 255) < ICN_BCH) {				a = c->arg;				switch (a >> 8) {					case ISDN_PROTO_L2_X75I:						sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1);						break;					case ISDN_PROTO_L2_HDLC:						sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1);						break;					default:						return -EINVAL;				}				i = icn_writecmd(cbuf, strlen(cbuf), 0, card);				card->l2_proto[a & 255] = (a >> 8);			}			break;		case ISDN_CMD_SETL3:			if (!card->flags & ICN_FLAGS_RUNNING)				return -ENODEV;			return 0;		default:			return -EINVAL;	}	return 0;}/* * Find card with given driverId */static inline icn_card *icn_findcard(int driverid){	icn_card *p = cards;	while (p) {		if (p->myid == driverid)			return p;		p = p->next;	}	return (icn_card *) 0;}/* * Wrapper functions for interface to linklevel */static intif_command(isdn_ctrl * c){	icn_card *card = icn_findcard(c->driver);	if (card)		return (icn_command(c, card));	printk(KERN_ERR	       "icn: if_command %d called with invalid driverId %d!\n",	       c->command, c->driver);	return -ENODEV;}static intif_writecmd(const u_char __user *buf, int len, int id, int channel){	icn_card *card = icn_findcard(id);	if (card) {		if (!card->flags & ICN_FLAGS_RUNNING)			return -ENODEV;		return (icn_writecmd(buf, len, 1, card));	}	printk(KERN_ERR	       "icn: if_writecmd called with invalid driverId!\n");	return -ENODEV;}static intif_readstatus(u_char __user *buf, int len, int id, int channel){	icn_card *card = icn_findcard(id);	if (card) {		if (!card->flags & ICN_FLAGS_RUNNING)			return -ENODEV;		return (icn_readstatus(buf, len, card));	}	printk(KERN_ERR	       "icn: if_readstatus called with invalid driverId!\n");	return -ENODEV;}static intif_sendbuf(int id, int channel, int ack, struct sk_buff *skb){	icn_card *card = icn_findcard(id);	if (card) {		if (!card->flags & ICN_FLAGS_RUNNING)			return -ENODEV;		return (icn_sendbuf(channel, ack, skb, card));	}	printk(KERN_ERR	       "icn: 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 icn_card *icn_initcard(int port, char *id){	icn_card *card;	int i;	if (!(card = (icn_card *) kmalloc(sizeof(icn_card), GFP_KERNEL))) {		printk(KERN_WARNING		       "icn: (%s) Could not allocate card-struct.\n", id);		return (icn_card *) 0;	}	memset((char *) card, 0, sizeof(icn_card));	spin_lock_init(&card->lock);	card->port = port;	card->interface.owner = THIS_MODULE;	card->interface.hl_hdrlen = 1;	card->interface.channels = ICN_BCH;	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 |	    ISDN_FEATURE_L2_HDLC |	    ISDN_FEATURE_L3_TRANS |	    ISDN_FEATURE_P_UNKNOWN;	card->ptype = ISDN_PTYPE_UNKNOWN;	strlcpy(card->interface.id, id, sizeof(card->interface.id));	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 < ICN_BCH; i++) {		card->l2_proto[i] = ISDN_PROTO_L2_X75I;		skb_queue_head_init(&card->spqueue[i]);	}	card->next = cards;	cards = card;	if (!register_isdn(&card->interface)) {		cards = cards->next;		printk(KERN_WARNING		       "icn: Unable to register %s\n", id);		kfree(card);		return (icn_card *) 0;	}	card->myid = card->interface.channels;	sprintf(card->regname, "icn-isdn (%s)", card->interface.id);	return card;}static inticn_addcard(int port, char *id1, char *id2){	icn_card *card;	icn_card *card2;	if (!(card = icn_initcard(port, id1))) {		return -EIO;	}	if (!strlen(id2)) {		printk(KERN_INFO		       "icn: (%s) ICN-2B, port 0x%x added\n",		       card->interface.id, port);		return 0;	}	if (!(card2 = icn_initcard(port, id2))) {		printk(KERN_INFO		       "icn: (%s) half ICN-4B, port 0x%x added\n",		       card2->interface.id, port);		return 0;	}	card->doubleS0 = 1;	card->secondhalf = 0;	card->other = card2;	card2->doubleS0 = 1;	card2->secondhalf = 1;	card2->other = card;	printk(KERN_INFO	       "icn: (%s and %s) ICN-4B, port 0x%x added\n",	       card->interface.id, card2->interface.id, port);	return 0;}#ifndef MODULEstatic int __initicn_setup(char *line){	char *p, *str;	int	ints[3];	static char sid[20];	static char sid2[20];	str = get_options(line, 2, ints);	if (ints[0])		portbase = ints[1];	if (ints[0] > 1)		membase = (unsigned long)ints[2];	if (str && *str) {		strcpy(sid, str);		icn_id = sid;		if ((p = strchr(sid, ','))) {			*p++ = 0;			strcpy(sid2, p);			icn_id2 = sid2;		}	}	return(1);}__setup("icn=", icn_setup);#endif /* MODULE */static int __init icn_init(void){	char *p;	char rev[10];	memset(&dev, 0, sizeof(icn_dev));	dev.memaddr = (membase & 0x0ffc000);	dev.channel = -1;	dev.mcard = NULL;	dev.firstload = 1;	spin_lock_init(&dev.devlock);	if ((p = strchr(revision, ':'))) {		strcpy(rev, p + 1);		p = strchr(rev, '$');		*p = 0;	} else		strcpy(rev, " ??? ");	printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08lx\n", rev,	       dev.memaddr);	return (icn_addcard(portbase, icn_id, icn_id2));}static void __exit icn_exit(void){	isdn_ctrl cmd;	icn_card *card = cards;	icn_card *last, *tmpcard;	int i;	unsigned long flags;	icn_stopallcards();	while (card) {		cmd.command = ISDN_STAT_UNLOAD;		cmd.driver = card->myid;		card->interface.statcallb(&cmd);		spin_lock_irqsave(&card->lock, flags);		if (card->rvalid) {			OUTB_P(0, ICN_RUN);	/* Reset Controller     */			OUTB_P(0, ICN_MAPRAM);	/* Disable RAM          */			if (card->secondhalf || (!card->doubleS0)) {				release_region(card->port, ICN_PORTLEN);				card->rvalid = 0;			}			for (i = 0; i < ICN_BCH; i++)				icn_free_queue(card, i);		}		tmpcard = card->next;		spin_unlock_irqrestore(&card->lock, flags);		card = tmpcard;	}	card = cards;	cards = NULL;	while (card) {		last = card;		card = card->next;		kfree(last);	}	if (dev.mvalid) {		iounmap(dev.shmem);		release_mem_region(dev.memaddr, 0x4000);	}	printk(KERN_NOTICE "ICN-ISDN-driver unloaded\n");}module_init(icn_init);module_exit(icn_exit);

⌨️ 快捷键说明

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