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

📄 icn.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			if (card->xmit_lock[channel]) {				restore_flags(flags);				break;			}			card->xmit_lock[channel]++;			restore_flags(flags);			skb = skb_dequeue(&card->spqueue[channel]);			if (!skb)				break;			if (skb->len > ICN_FRAGSIZE) {				writeb(0xff, &sbuf_f);				cnt = ICN_FRAGSIZE;			} else {				writeb(0x0, &sbuf_f);				cnt = skb->len;			}			writeb(cnt, &sbuf_l);			memcpy_toio(&sbuf_d, skb->data, cnt);			skb_pull(skb, cnt);			card->sndcount[channel] -= cnt;			sbnext; /* switch to next buffer        */			icn_maprelease_channel(card, mch & 2);			if (!skb->len) {				dev_kfree_skb(skb, FREE_WRITE);				cmd.command = ISDN_STAT_BSENT;				cmd.driver = card->myid;				cmd.arg = channel;				card->interface.statcallb(&cmd);			} else				skb_queue_head(&card->spqueue[channel], skb);			card->xmit_lock[channel] = 0;			if (!icn_trymaplock_channel(card, mch))				break;		}		icn_maprelease_channel(card, mch & 2);	}}/* Send/Receive Data to/from the B-Channel. * This routine is called via timer-callback. * It schedules itself while any B-Channel is open. */static voidicn_pollbchan(unsigned long data){	icn_card *card = (icn_card *) data;	unsigned long flags;	if (card->flags & ICN_FLAGS_B1ACTIVE) {		icn_pollbchan_receive(0, card);		icn_pollbchan_send(0, card);	}	if (card->flags & ICN_FLAGS_B2ACTIVE) {		icn_pollbchan_receive(1, card);		icn_pollbchan_send(1, card);	}	if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE)) {		/* schedule b-channel polling again */		save_flags(flags);		cli();		del_timer(&card->rb_timer);		card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD;		add_timer(&card->rb_timer);		card->flags |= ICN_FLAGS_RBTIMER;		restore_flags(flags);	} else		card->flags &= ~ICN_FLAGS_RBTIMER;}typedef struct icn_stat {	char *statstr;	int command;	int action;} icn_stat;/* *INDENT-OFF* */static icn_stat icn_stat_table[] ={	{"BCON_",          ISDN_STAT_BCONN, 1},	/* B-Channel connected        */	{"BDIS_",          ISDN_STAT_BHUP,  2},	/* B-Channel disconnected     */#ifdef CONFIG_ISDN_WITH_ABC	{"DCON_",          ISDN_STAT_DCONN, 10}, /* D-Channel connected       */	{"DDIS_",          ISDN_STAT_DHUP,  11}, /* D-Channel disconnected    */#else	{"DCON_",          ISDN_STAT_DCONN, 0}, /* D-Channel connected        */	{"DDIS_",          ISDN_STAT_DHUP,  0}, /* D-Channel disconnected     */#endif	{"DCAL_I",         ISDN_STAT_ICALL, 3},	/* Incoming call dialup-line  */	{"DSCA_I",         ISDN_STAT_ICALL, 3},	/* Incoming call 1TR6-SPV     */	{"FCALL",          ISDN_STAT_ICALL, 4},	/* Leased line connection up  */	{"CIF",            ISDN_STAT_CINF,  5},	/* Charge-info, 1TR6-type     */	{"AOC",            ISDN_STAT_CINF,  6},	/* Charge-info, DSS1-type     */	{"CAU",            ISDN_STAT_CAUSE, 7},	/* Cause code                 */	{"TEI OK",         ISDN_STAT_RUN,   0},	/* Card connected to wallplug */	{"NO D-CHAN",      ISDN_STAT_NODCH, 0},	/* No D-channel available     */	{"E_L1: ACT FAIL", ISDN_STAT_BHUP,  8},	/* Layer-1 activation failed  */	{"E_L2: DATA LIN", ISDN_STAT_BHUP,  8},	/* Layer-2 data link lost     */	{"E_L1: ACTIVATION FAILED",					   ISDN_STAT_BHUP,  8},	/* Layer-1 activation failed  */	{NULL, 0, -1}};/* *INDENT-ON* *//* * Check Statusqueue-Pointer from isdn-cards. * If there are new status-replies from the interface, check * them against B-Channel-connects/disconnects and set flags accordingly. * Wake-Up any processes, who are reading the status-device. * If there are B-Channels open, initiate a timer-callback to * icn_pollbchan(). * This routine is called periodically via timer. */static inticn_parse_status(u_char * status, int channel, icn_card * card){	icn_stat *s = icn_stat_table;	int action = -1;	int dflag = 0;	unsigned long flags;	isdn_ctrl cmd;	while (s->statstr) {		if (!strncmp(status, s->statstr, strlen(s->statstr))) {			cmd.command = s->command;			action = s->action;			break;		}		s++;	}	if (action == -1)		return 0;	cmd.driver = card->myid;	cmd.arg = channel;	switch (action) {#ifdef CONFIG_ISDN_WITH_ABC	case 11:		save_flags(flags);		cli();		icn_free_queue(card,channel);		card->rcvidx[channel] = 0;		if( card->flags & 			((channel)?ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE)) {			isdn_ctrl ncmd;			printk(KERN_INFO "icn: D-Channel hangup before B-Channel hangup\n");			card->flags &= ~((channel)?					ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE);			memset(&ncmd,0,sizeof(ncmd));			ncmd.driver = card->myid;			ncmd.arg = channel;			ncmd.command = ISDN_STAT_BHUP;			restore_flags(flags);			card->interface.statcallb(&cmd);			dflag |= (channel+1);		} else restore_flags(flags);				break;#endif		case 1:#ifdef CONFIG_ISDN_WITH_ABC			icn_free_queue(card,channel);#endif			card->flags |= (channel) ?			    ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE;			break;		case 2:			card->flags &= ~((channel) ?				ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE);			icn_free_queue(card, channel);			save_flags(flags);			cli();			card->rcvidx[channel] = 0;			restore_flags(flags);			dflag |= (channel + 1);			break;		case 3:			{				char *t = status + 6;				char *s = strpbrk(t, ",");				memset(&cmd.parm.setup, 0, sizeof(cmd.parm.setup));				if (!s)					break;				*s++ = '\0';				strncpy(cmd.parm.setup.phone, t,					sizeof(cmd.parm.setup.phone));				if (!(s = strpbrk(t = s, ",")))					break;				*s++ = '\0';				if (!strlen(t))					cmd.parm.setup.si1 = 0;				else					cmd.parm.setup.si1 =					    simple_strtoul(t, NULL, 10);				if (!(s = strpbrk(t = s, ",")))					break;				*s++ = '\0';				if (!strlen(t))					cmd.parm.setup.si2 = 0;				else					cmd.parm.setup.si2 =					    simple_strtoul(t, NULL, 10);				strncpy(cmd.parm.setup.eazmsn, s,					sizeof(cmd.parm.setup.eazmsn));			}			break;		case 4:			sprintf(cmd.parm.setup.phone, "LEASED%d", card->myid);			sprintf(cmd.parm.setup.eazmsn, "%d", channel + 1);			cmd.parm.setup.si1 = 7;			cmd.parm.setup.si2 = 0;			cmd.parm.setup.plan = 0;			cmd.parm.setup.screen = 0;			break;		case 5:			strncpy(cmd.parm.num, status + 3, sizeof(cmd.parm.num) - 1);			break;		case 6:			sprintf(cmd.parm.num, "%d",			     (int) simple_strtoul(status + 7, NULL, 16));			break;		case 7:			status += 3;			if (strlen(status) == 4)				sprintf(cmd.parm.num, "%s%c%c",				     status + 2, *status, *(status + 1));			else				strncpy(cmd.parm.num, status + 1, sizeof(cmd.parm.num) - 1);			break;		case 8:			dflag = 3;			card->flags &= ~ICN_FLAGS_B1ACTIVE;			icn_free_queue(card, 0);			save_flags(flags);			cli();			card->rcvidx[0] = 0;			restore_flags(flags);			cmd.arg = 0;			cmd.driver = card->myid;			card->interface.statcallb(&cmd);			cmd.command = ISDN_STAT_DHUP;			cmd.arg = 0;			cmd.driver = card->myid;			card->interface.statcallb(&cmd);			cmd.command = ISDN_STAT_BHUP;			card->flags &= ~ICN_FLAGS_B2ACTIVE;			icn_free_queue(card, 1);			save_flags(flags);			cli();			card->rcvidx[1] = 0;			restore_flags(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 dflag;}static voidicn_putmsg(icn_card * card, unsigned char c){	ulong flags;	save_flags(flags);	cli();	*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;	restore_flags(flags);}static voidicn_polldchan(unsigned long data){	icn_card *card = (icn_card *) data;	int mch = card->secondhalf ? 2 : 0;	int avail = 0;	int dflag = 0;	int left;	u_char c;	int ch;	int 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];					dflag |= 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);	}	if (dflag & 1)		card->interface.rcvcallb(card->myid, 0, card->rcvbuf[0], 0);	if (dflag & 2)		card->interface.rcvcallb(card->myid, 1, card->rcvbuf[1], 0);	if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE))		if (!(card->flags & ICN_FLAGS_RBTIMER)) {			/* schedule b-channel polling */			card->flags |= ICN_FLAGS_RBTIMER;			save_flags(flags);			cli();			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);			restore_flags(flags);		}	/* schedule again */	save_flags(flags);	cli();	del_timer(&card->st_timer);	card->st_timer.expires = jiffies + ICN_TIMER_DCREAD;	add_timer(&card->st_timer);	restore_flags(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, 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;		save_flags(flags);		cli();		nskb = skb_clone(skb, GFP_ATOMIC);		if (nskb) {			skb_queue_tail(&card->spqueue[channel], nskb);			dev_kfree_skb(skb, FREE_WRITE);		} else			len = 0;		card->sndcount[channel] += len;		restore_flags(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			current->state = TASK_INTERRUPTIBLE;			current->timeout = jiffies + ICN_BOOT_TIMEOUT1;			schedule();		} 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:

⌨️ 快捷键说明

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