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

📄 icn.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
			cmd.arg = 0;			cmd.driver = card->myid;			card->interface.statcallb(&cmd);			cmd.command = ISDN_STAT_BHUP;			spin_lock_irqsave(&card->lock, flags);			card->flags &= ~ICN_FLAGS_B2ACTIVE;			icn_free_queue(card, 1);			card->rcvidx[1] = 0;			spin_unlock_irqrestore(&card->lock, flags);			cmd.arg = 1;			cmd.driver = card->myid;			card->interface.statcallb(&cmd);			cmd.command = ISDN_STAT_DHUP;			cmd.arg = 1;			cmd.driver = card->myid;			break;	}	card->interface.statcallb(&cmd);	return;}static voidicn_putmsg(icn_card * card, unsigned char c){	ulong flags;	spin_lock_irqsave(&card->lock, flags);	*card->msg_buf_write++ = (c == 0xff) ? '\n' : c;	if (card->msg_buf_write == card->msg_buf_read) {		if (++card->msg_buf_read > card->msg_buf_end)			card->msg_buf_read = card->msg_buf;	}	if (card->msg_buf_write > card->msg_buf_end)		card->msg_buf_write = card->msg_buf;	spin_unlock_irqrestore(&card->lock, flags);}static voidicn_polldchan(unsigned long data){	icn_card *card = (icn_card *) data;	int mch = card->secondhalf ? 2 : 0;	int avail = 0;	int left;	u_char c;	int ch;	unsigned long flags;	int i;	u_char *p;	isdn_ctrl cmd;	if (icn_trymaplock_channel(card, mch)) {		avail = msg_avail;		for (left = avail, i = readb(&msg_o); left > 0; i++, left--) {			c = readb(&dev.shmem->comm_buffers.iopc_buf[i & 0xff]);			icn_putmsg(card, c);			if (c == 0xff) {				card->imsg[card->iptr] = 0;				card->iptr = 0;				if (card->imsg[0] == '0' && card->imsg[1] >= '0' &&				    card->imsg[1] <= '2' && card->imsg[2] == ';') {					ch = (card->imsg[1] - '0') - 1;					p = &card->imsg[3];					icn_parse_status(p, ch, card);				} else {					p = card->imsg;					if (!strncmp(p, "DRV1.", 5)) {						u_char vstr[10];						u_char *q = vstr;						printk(KERN_INFO "icn: (%s) %s\n", CID, p);						if (!strncmp(p + 7, "TC", 2)) {							card->ptype = ISDN_PTYPE_1TR6;							card->interface.features |= ISDN_FEATURE_P_1TR6;							printk(KERN_INFO							       "icn: (%s) 1TR6-Protocol loaded and running\n", CID);						}						if (!strncmp(p + 7, "EC", 2)) {							card->ptype = ISDN_PTYPE_EURO;							card->interface.features |= ISDN_FEATURE_P_EURO;							printk(KERN_INFO							       "icn: (%s) Euro-Protocol loaded and running\n", CID);						}						p = strstr(card->imsg, "BRV") + 3;						while (*p) {							if (*p >= '0' && *p <= '9')								*q++ = *p;							p++;						}						*q = '\0';						strcat(vstr, "000");						vstr[3] = '\0';						card->fw_rev = (int) simple_strtoul(vstr, NULL, 10);						continue;					}				}			} else {				card->imsg[card->iptr] = c;				if (card->iptr < 59)					card->iptr++;			}		}		writeb((readb(&msg_o) + avail) & 0xff, &msg_o);		icn_release_channel();	}	if (avail) {		cmd.command = ISDN_STAT_STAVAIL;		cmd.driver = card->myid;		cmd.arg = avail;		card->interface.statcallb(&cmd);	}	spin_lock_irqsave(&card->lock, flags);	if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE))		if (!(card->flags & ICN_FLAGS_RBTIMER)) {			/* schedule b-channel polling */			card->flags |= ICN_FLAGS_RBTIMER;			del_timer(&card->rb_timer);			card->rb_timer.function = icn_pollbchan;			card->rb_timer.data = (unsigned long) card;			card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD;			add_timer(&card->rb_timer);		}	/* schedule again */	mod_timer(&card->st_timer, jiffies+ICN_TIMER_DCREAD);	spin_unlock_irqrestore(&card->lock, flags);}/* Append a packet to the transmit buffer-queue. * Parameters: *   channel = Number of B-channel *   skb     = pointer to sk_buff *   card    = pointer to card-struct * Return: *   Number of bytes transferred, -E??? on error */static inticn_sendbuf(int channel, int ack, struct sk_buff *skb, icn_card * card){	int len = skb->len;	unsigned long flags;	struct sk_buff *nskb;	if (len > 4000) {		printk(KERN_WARNING		       "icn: Send packet too large\n");		return -EINVAL;	}	if (len) {		if (!(card->flags & (channel) ? ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE))			return 0;		if (card->sndcount[channel] > ICN_MAX_SQUEUE)			return 0;		#warning TODO test headroom or use skb->nb to flag ACK		nskb = skb_clone(skb, GFP_ATOMIC);		if (nskb) {			/* Push ACK flag as one			 * byte in front of data.			 */			*(skb_push(nskb, 1)) = ack?1:0;			skb_queue_tail(&card->spqueue[channel], nskb);			dev_kfree_skb(skb);		} else			len = 0;		spin_lock_irqsave(&card->lock, flags);		card->sndcount[channel] += len;		spin_unlock_irqrestore(&card->lock, flags);	}	return len;}/* * Check card's status after starting the bootstrap loader. * On entry, the card's shared memory has already to be mapped. * Return: *   0 on success (Boot loader ready) *   -EIO on failure (timeout) */static inticn_check_loader(int cardnumber){	int timer = 0;	while (1) {#ifdef BOOT_DEBUG		printk(KERN_DEBUG "Loader %d ?\n", cardnumber);#endif		if (readb(&dev.shmem->data_control.scns) ||		    readb(&dev.shmem->data_control.scnr)) {			if (timer++ > 5) {				printk(KERN_WARNING				       "icn: Boot-Loader %d timed out.\n",				       cardnumber);				icn_release_channel();				return -EIO;			}#ifdef BOOT_DEBUG			printk(KERN_DEBUG "Loader %d TO?\n", cardnumber);#endif			msleep_interruptible(ICN_BOOT_TIMEOUT1);		} else {#ifdef BOOT_DEBUG			printk(KERN_DEBUG "Loader %d OK\n", cardnumber);#endif			icn_release_channel();			return 0;		}	}}/* Load the boot-code into the interface-card's memory and start it. * Always called from user-process. * * Parameters: *            buffer = pointer to packet * Return: *        0 if successfully loaded */#ifdef BOOT_DEBUG#define SLEEP(sec) { \int slsec = sec; \  printk(KERN_DEBUG "SLEEP(%d)\n",slsec); \  while (slsec) { \    msleep_interruptible(1000); \    slsec--; \  } \}#else#define SLEEP(sec)#endifstatic inticn_loadboot(u_char __user * buffer, icn_card * card){	int ret;	u_char *codebuf;	unsigned long flags;#ifdef BOOT_DEBUG	printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer);#endif	if (!(codebuf = kmalloc(ICN_CODE_STAGE1, GFP_KERNEL))) {		printk(KERN_WARNING "icn: Could not allocate code buffer\n");		ret = -ENOMEM;		goto out;	}	if (copy_from_user(codebuf, buffer, ICN_CODE_STAGE1)) {		ret = -EFAULT;		goto out_kfree;	}	if (!card->rvalid) {		if (!request_region(card->port, ICN_PORTLEN, card->regname)) {			printk(KERN_WARNING			       "icn: (%s) ports 0x%03x-0x%03x in use.\n",			       CID,			       card->port,			       card->port + ICN_PORTLEN);			ret = -EBUSY;			goto out_kfree;		}		card->rvalid = 1;		if (card->doubleS0)			card->other->rvalid = 1;	}	if (!dev.mvalid) {		if (!request_mem_region(dev.memaddr, 0x4000, "icn-isdn (all cards)")) {			printk(KERN_WARNING			       "icn: memory at 0x%08lx in use.\n", dev.memaddr);			ret = -EBUSY;			goto out_kfree;		}		dev.shmem = ioremap(dev.memaddr, 0x4000);		dev.mvalid = 1;	}	OUTB_P(0, ICN_RUN);     /* Reset Controller */	OUTB_P(0, ICN_MAPRAM);  /* Disable RAM      */	icn_shiftout(ICN_CFG, 0x0f, 3, 4);	/* Windowsize= 16k  */	icn_shiftout(ICN_CFG, dev.memaddr, 23, 10);	/* Set RAM-Addr.    */#ifdef BOOT_DEBUG	printk(KERN_DEBUG "shmem=%08lx\n", dev.memaddr);#endif	SLEEP(1);#ifdef BOOT_DEBUG	printk(KERN_DEBUG "Map Bank 0\n");#endif	spin_lock_irqsave(&dev.devlock, flags);	icn_map_channel(card, 0);	/* Select Bank 0    */	icn_lock_channel(card, 0);	/* Lock Bank 0      */	spin_unlock_irqrestore(&dev.devlock, flags);	SLEEP(1);	memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1);	/* Copy code        */#ifdef BOOT_DEBUG	printk(KERN_DEBUG "Bootloader transferred\n");#endif	if (card->doubleS0) {		SLEEP(1);#ifdef BOOT_DEBUG		printk(KERN_DEBUG "Map Bank 8\n");#endif		spin_lock_irqsave(&dev.devlock, flags);		__icn_release_channel();		icn_map_channel(card, 2);	/* Select Bank 8   */		icn_lock_channel(card, 2);	/* Lock Bank 8     */		spin_unlock_irqrestore(&dev.devlock, flags);		SLEEP(1);		memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1);	/* Copy code        */#ifdef BOOT_DEBUG		printk(KERN_DEBUG "Bootloader transferred\n");#endif	}	SLEEP(1);	OUTB_P(0xff, ICN_RUN);  /* Start Boot-Code */	if ((ret = icn_check_loader(card->doubleS0 ? 2 : 1))) {		goto out_kfree;	}	if (!card->doubleS0) {		ret = 0;		goto out_kfree;	}	/* reached only, if we have a Double-S0-Card */#ifdef BOOT_DEBUG	printk(KERN_DEBUG "Map Bank 0\n");#endif	spin_lock_irqsave(&dev.devlock, flags);	icn_map_channel(card, 0);	/* Select Bank 0   */	icn_lock_channel(card, 0);	/* Lock Bank 0     */	spin_unlock_irqrestore(&dev.devlock, flags);	SLEEP(1);	ret = (icn_check_loader(1)); out_kfree:	kfree(codebuf); out:	return ret;}static inticn_loadproto(u_char __user * buffer, icn_card * card){	register u_char __user *p = buffer;	u_char codebuf[256];	uint left = ICN_CODE_STAGE2;	uint cnt;	int timer;	unsigned long flags;#ifdef BOOT_DEBUG	printk(KERN_DEBUG "icn_loadproto called\n");#endif	if (!access_ok(VERIFY_READ, buffer, ICN_CODE_STAGE2))		return -EFAULT;	timer = 0;	spin_lock_irqsave(&dev.devlock, flags);	if (card->secondhalf) {		icn_map_channel(card, 2);		icn_lock_channel(card, 2);	} else {		icn_map_channel(card, 0);		icn_lock_channel(card, 0);	}	spin_unlock_irqrestore(&dev.devlock, flags);	while (left) {		if (sbfree) {   /* If there is a free buffer...  */			cnt = left;			if (cnt > 256)				cnt = 256;			if (copy_from_user(codebuf, p, cnt)) {				icn_maprelease_channel(card, 0);				return -EFAULT;			}			memcpy_toio(&sbuf_l, codebuf, cnt);	/* copy data                     */			sbnext; /* switch to next buffer         */			p += cnt;			left -= cnt;			timer = 0;		} else {#ifdef BOOT_DEBUG			printk(KERN_DEBUG "boot 2 !sbfree\n");#endif			if (timer++ > 5) {				icn_maprelease_channel(card, 0);				return -EIO;			}			schedule_timeout_interruptible(10);		}	}	writeb(0x20, &sbuf_n);	timer = 0;	while (1) {		if (readb(&cmd_o) || readb(&cmd_i)) {#ifdef BOOT_DEBUG			printk(KERN_DEBUG "Proto?\n");#endif			if (timer++ > 5) {				printk(KERN_WARNING				       "icn: (%s) Protocol timed out.\n",				       CID);#ifdef BOOT_DEBUG				printk(KERN_DEBUG "Proto TO!\n");#endif				icn_maprelease_channel(card, 0);				return -EIO;			}#ifdef BOOT_DEBUG			printk(KERN_DEBUG "Proto TO?\n");#endif			msleep_interruptible(ICN_BOOT_TIMEOUT1);		} else {			if ((card->secondhalf) || (!card->doubleS0)) {#ifdef BOOT_DEBUG				printk(KERN_DEBUG "Proto loaded, install poll-timer %d\n",				       card->secondhalf);#endif				spin_lock_irqsave(&card->lock, flags);				init_timer(&card->st_timer);				card->st_timer.expires = jiffies + ICN_TIMER_DCREAD;				card->st_timer.function = icn_polldchan;				card->st_timer.data = (unsigned long) card;				add_timer(&card->st_timer);				card->flags |= ICN_FLAGS_RUNNING;				if (card->doubleS0) {					init_timer(&card->other->st_timer);					card->other->st_timer.expires = jiffies + ICN_TIMER_DCREAD;					card->other->st_timer.function = icn_polldchan;					card->other->st_timer.data = (unsigned long) card->other;					add_timer(&card->other->st_timer);					card->other->flags |= ICN_FLAGS_RUNNING;				}				spin_unlock_irqrestore(&card->lock, flags);			}			icn_maprelease_channel(card, 0);			return 0;		}	}}/* Read the Status-replies from the Interface */static inticn_readstatus(u_char __user *buf, int len, icn_card * card){	int count;	u_char __user *p;	for (p = buf, count = 0; count < len; p++, count++) {		if (card->msg_buf_read == card->msg_buf_write)			return count;		put_user(*card->msg_buf_read++, p);		if (card->msg_buf_read > card->msg_buf_end)			card->msg_buf_read = card->msg_buf;	}	return count;}/* Put command-strings into the command-queue of the Interface */static inticn_writecmd(const u_char * buf, int len, int user, icn_card * card){	int mch = card->secondhalf ? 2 : 0;	int pp;	int i;	int count;	int xcount;	int ocount;	int loop;	unsigned long flags;	int lastmap_channel;	struct icn_card *lastmap_card;	u_char *p;	isdn_ctrl cmd;	u_char msg[0x100];	ocount = 1;	xcount = loop = 0;	while (len) {		count = cmd_free;		if (count > len)			count = len;		if (user) {			if (copy_from_user(msg, buf, count))				return -EFAULT;		} else			memcpy(msg, buf, count);		spin_lock_irqsave(&dev.devlock, flags);		lastmap_card = dev.mcard;		lastmap_channel = dev.channel;		icn_map_channel(card, mch);		icn_putmsg(card, '>');		for (p = msg, pp = readb(&cmd_i), i = count; i > 0; i--, p++, pp		     ++) {			writeb((*p == '\n') ? 0xff : *p,			   &dev.shmem->comm_buffers.pcio_buf[pp & 0xff]);			len--;			xcount++;			icn_putmsg(card, *p);			if ((*p == '\n') && (i > 1)) {				icn_putmsg(card, '>');				ocount++;			}			ocount++;		}		writeb((readb(&cmd_i) + count) & 0xff, &cmd_i);		if (lastmap_card)			icn_map_channel(lastmap_card, lastmap_channel);		spin_unlock_irqrestore(&dev.devlock, flags);		if (len) {			mdelay(1);			if (loop++ > 20)				break;		} else			break;	}	if (len && (!user))		printk(KERN_WARNING "icn: writemsg incomplete!\n");	cmd.command = ISDN_STAT_STAVAIL;	cmd.driver = card->myid;	cmd.arg = ocount;	card->interface.statcallb(&cmd);	return xcount;}/* * Delete card's pending timers, send STOP to linklevel */static voidicn_stopcard(icn_card * card){	unsigned long flags;	isdn_ctrl cmd;	spin_lock_irqsave(&card->lock, flags);	if (card->flags & ICN_FLAGS_RUNNING) {		card->flags &= ~ICN_FLAGS_RUNNING;		del_timer(&card->st_timer);		del_timer(&card->rb_timer);		spin_unlock_irqrestore(&card->lock, flags);		cmd.command = ISDN_STAT_STOP;		cmd.driver = card->myid;		card->interface.statcallb(&cmd);		if (card->doubleS0)			icn_stopcard(card->other);	} else		spin_unlock_irqrestore(&card->lock, flags);}static voidicn_stopallcards(void){	icn_card *p = cards;	while (p) {		icn_stopcard(p);		p = p->next;	}}/* * Unmap all cards, because some of them may be mapped accidetly during * autoprobing of some network drivers (SMC-driver?) */static void

⌨️ 快捷键说明

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