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

📄 capidrv.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
			plcip->leasedline = isleasedline;			plci_change_state(card, plcip, EV_PLCI_CONNECT_REQ);			send_message(card, &cmdcmsg);			return 0;		}	case ISDN_CMD_ACCEPTD:		bchan = &card->bchans[c->arg % card->nbchan];		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%d\n",			       card->contrnr,			       c->arg, bchan->l2, bchan->l3);		capi_fill_CONNECT_RESP(&cmdcmsg,				       global.appid,				       card->msgid++,				       bchan->plcip->plci,	/* adr */				       0,	/* Reject */				       b1prot(bchan->l2, bchan->l3),	/* B1protocol */				       b2prot(bchan->l2, bchan->l3),	/* B2protocol */				       b3prot(bchan->l2, bchan->l3),	/* B3protocol */				       b1config(bchan->l2, bchan->l3),	/* B1configuration */				       0,	/* B2configuration */				       0,	/* B3configuration */				       0,	/* ConnectedNumber */				       0,	/* ConnectedSubaddress */				       0,	/* LLC */				       0,	/* BChannelinformation */				       0,	/* Keypadfacility */				       0,	/* Useruserdata */				       0	/* Facilitydataarray */		);		capi_cmsg2message(&cmdcmsg, cmdcmsg.buf);		plci_change_state(card, bchan->plcip, EV_PLCI_CONNECT_RESP);		send_message(card, &cmdcmsg);		return 0;	case ISDN_CMD_ACCEPTB:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n",			       card->contrnr,			       c->arg);		return -ENOSYS;	case ISDN_CMD_HANGUP:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n",			       card->contrnr,			       c->arg);		bchan = &card->bchans[c->arg % card->nbchan];		if (bchan->disconnecting) {			if (debugmode)				printk(KERN_DEBUG "capidrv-%d: chan %ld already disconnecting ...\n",				       card->contrnr,				       c->arg);			return 0;		}		if (bchan->nccip) {			bchan->disconnecting = 1;			capi_fill_DISCONNECT_B3_REQ(&cmdcmsg,						    global.appid,						    card->msgid++,						    bchan->nccip->ncci,						    0	/* NCPI */			);			ncci_change_state(card, bchan->nccip, EV_NCCI_DISCONNECT_B3_REQ);			send_message(card, &cmdcmsg);			return 0;		} else if (bchan->plcip) {			if (bchan->plcip->state == ST_PLCI_INCOMING) {				/*				 * just ignore, we a called from				 * isdn_status_callback(),				 * which will return 0 or 2, this is handled				 * by the CONNECT_IND handler				 */				bchan->disconnecting = 1;				return 0;			} else if (bchan->plcip->plci) {				bchan->disconnecting = 1;				capi_fill_DISCONNECT_REQ(&cmdcmsg,							 global.appid,							 card->msgid++,						      bchan->plcip->plci,							 0,	/* BChannelinformation */							 0,	/* Keypadfacility */							 0,	/* Useruserdata */							 0	/* Facilitydataarray */				);				plci_change_state(card, bchan->plcip, EV_PLCI_DISCONNECT_REQ);				send_message(card, &cmdcmsg);				return 0;			} else {				printk(KERN_ERR "capidrv-%d: chan %ld disconnect request while waiting for CONNECT_CONF\n",				       card->contrnr,				       c->arg);				return -EINVAL;			}		}		printk(KERN_ERR "capidrv-%d: chan %ld disconnect request on free channel\n",				       card->contrnr,				       c->arg);		return -EINVAL;/* ready */	case ISDN_CMD_SETL2:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: set L2 on chan %ld to %ld\n",			       card->contrnr,			       (c->arg & 0xff), (c->arg >> 8));		bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];		bchan->l2 = (c->arg >> 8);		return 0;	case ISDN_CMD_SETL3:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: set L3 on chan %ld to %ld\n",			       card->contrnr,			       (c->arg & 0xff), (c->arg >> 8));		bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];		bchan->l3 = (c->arg >> 8);		return 0;	case ISDN_CMD_SETEAZ:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: set EAZ \"%s\" on chan %ld\n",			       card->contrnr,			       c->parm.num, c->arg);		bchan = &card->bchans[c->arg % card->nbchan];		strncpy(bchan->msn, c->parm.num, ISDN_MSNLEN);		return 0;	case ISDN_CMD_CLREAZ:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: clearing EAZ on chan %ld\n",					card->contrnr, c->arg);		bchan = &card->bchans[c->arg % card->nbchan];		bchan->msn[0] = 0;		return 0;	case ISDN_CMD_LOCK:		if (debugmode > 1)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_LOCK (%ld)\n", card->contrnr, c->arg);		MOD_INC_USE_COUNT;		break;	case ISDN_CMD_UNLOCK:		if (debugmode > 1)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_UNLOCK (%ld)\n",					card->contrnr, c->arg);		MOD_DEC_USE_COUNT;		break;/* never called */	case ISDN_CMD_GETL2:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL2\n",					card->contrnr);		return -ENODEV;	case ISDN_CMD_GETL3:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL3\n",					card->contrnr);		return -ENODEV;	case ISDN_CMD_GETEAZ:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETEAZ\n",					card->contrnr);		return -ENODEV;	case ISDN_CMD_SETSIL:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_SETSIL\n",					card->contrnr);		return -ENODEV;	case ISDN_CMD_GETSIL:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETSIL\n",					card->contrnr);		return -ENODEV;	default:		printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?\n",					card->contrnr, c->command);		return -EINVAL;	}	return 0;}static int if_command(isdn_ctrl * c){	capidrv_contr *card = findcontrbydriverid(c->driver);	if (card)		return capidrv_command(c, card);	printk(KERN_ERR	     "capidrv: if_command %d called with invalid driverId %d!\n",						c->command, c->driver);	return -ENODEV;}static _cmsg sendcmsg;static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb){	capidrv_contr *card = findcontrbydriverid(id);	capidrv_bchan *bchan;	capidrv_ncci *nccip;	int len = skb->len;	size_t msglen;	__u16 errcode;	__u16 datahandle;	if (!card) {		printk(KERN_ERR "capidrv-%d: if_sendbuf called with invalid driverId %d!\n",		       card->contrnr, id);		return 0;	}	if (debugmode > 1)		printk(KERN_DEBUG "capidrv-%d: sendbuf len=%d skb=%p doack=%d\n",					card->contrnr, len, skb, doack);	bchan = &card->bchans[channel % card->nbchan];	nccip = bchan->nccip;	if (!nccip || nccip->state != ST_NCCI_ACTIVE) {		printk(KERN_ERR "capidrv-%d: if_sendbuf: %s:%d: chan not up!\n",		       card->contrnr, card->name, channel);		return 0;	}	datahandle = nccip->datahandle;	capi_fill_DATA_B3_REQ(&sendcmsg, global.appid, card->msgid++,			      nccip->ncci,	/* adr */			      (__u32) skb->data,	/* Data */			      skb->len,		/* DataLength */			      datahandle,	/* DataHandle */			      0	/* Flags */	    );	if (capidrv_add_ack(nccip, datahandle, doack ? skb->len : -1) < 0)	   return 0;	capi_cmsg2message(&sendcmsg, sendcmsg.buf);	msglen = CAPIMSG_LEN(sendcmsg.buf);	if (skb_headroom(skb) < msglen) {		struct sk_buff *nskb = skb_realloc_headroom(skb, msglen);		if (!nskb) {			printk(KERN_ERR "capidrv-%d: if_sendbuf: no memory\n",				card->contrnr);		        (void)capidrv_del_ack(nccip, datahandle);			return 0;		}		printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom, need %d\n",		       card->contrnr, skb_headroom(skb), msglen);		memcpy(skb_push(nskb, msglen), sendcmsg.buf, msglen);		errcode = (*capifuncs->capi_put_message) (global.appid, nskb);		if (errcode == CAPI_NOERROR) {			dev_kfree_skb(skb);			nccip->datahandle++;			global.nsentdatapkt++;			return len;		}	        (void)capidrv_del_ack(nccip, datahandle);	        dev_kfree_skb(nskb);		return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;	} else {		memcpy(skb_push(skb, msglen), sendcmsg.buf, msglen);		errcode = (*capifuncs->capi_put_message) (global.appid, skb);		if (errcode == CAPI_NOERROR) {			nccip->datahandle++;			global.nsentdatapkt++;			return len;		}		skb_pull(skb, msglen);	        (void)capidrv_del_ack(nccip, datahandle);		return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;	}}static int if_readstat(__u8 *buf, int len, int user, int id, int channel){	capidrv_contr *card = findcontrbydriverid(id);	int count;	__u8 *p;	if (!card) {		printk(KERN_ERR "capidrv-%d: if_readstat called with invalid driverId %d!\n",		       card->contrnr, id);		return -ENODEV;	}	for (p=buf, count=0; count < len; p++, count++) {	        if (user)	                put_user(*card->q931_read++, p);	        else	                *p = *card->q931_read++;	        if (card->q931_read > card->q931_end)	                card->q931_read = card->q931_buf;	}	return count;}static void enable_dchannel_trace(capidrv_contr *card){        __u8 manufacturer[CAPI_MANUFACTURER_LEN];        capi_version version;	__u16 contr = card->contrnr;	__u16 errcode;	__u16 avmversion[3];        errcode = (*capifuncs->capi_get_manufacturer)(contr, manufacturer);        if (errcode != CAPI_NOERROR) {	   printk(KERN_ERR "%s: can't get manufacturer (0x%x)\n",			card->name, errcode);	   return;	}	if (strstr(manufacturer, "AVM") == 0) {	   printk(KERN_ERR "%s: not from AVM, no d-channel trace possible (%s)\n",			card->name, manufacturer);	   return;	}        errcode = (*capifuncs->capi_get_version)(contr, &version);        if (errcode != CAPI_NOERROR) {	   printk(KERN_ERR "%s: can't get version (0x%x)\n",			card->name, errcode);	   return;	}	avmversion[0] = (version.majormanuversion >> 4) & 0x0f;	avmversion[1] = (version.majormanuversion << 4) & 0xf0;	avmversion[1] |= (version.minormanuversion >> 4) & 0x0f;	avmversion[2] |= version.minormanuversion & 0x0f;        if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) {		printk(KERN_INFO "%s: D2 trace enabled\n", card->name);		capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,					   card->msgid++,					   contr,					   0x214D5641,  /* ManuID */					   0,           /* Class */					   1,           /* Function */					   (_cstruct)"\004\200\014\000\000");	} else {		printk(KERN_INFO "%s: D3 trace enabled\n", card->name);		capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,					   card->msgid++,					   contr,					   0x214D5641,  /* ManuID */					   0,           /* Class */					   1,           /* Function */					   (_cstruct)"\004\002\003\000\000");	}	send_message(card, &cmdcmsg);}static void send_listen(capidrv_contr *card){	capi_fill_LISTEN_REQ(&cmdcmsg, global.appid,			     card->msgid++,			     card->contrnr, /* controller */			     1 << 6,	/* Infomask */			     card->cipmask,			     card->cipmask2,			     0, 0);	send_message(card, &cmdcmsg);	listen_change_state(card, EV_LISTEN_REQ);}static void listentimerfunc(unsigned long x){	capidrv_contr *card = (capidrv_contr *)x;	if (card->state != ST_LISTEN_NONE && card->state != ST_LISTEN_ACTIVE)		printk(KERN_ERR "%s: controller dead ??\n", card->name);        send_listen(card);	mod_timer(&card->listentimer, jiffies + 60*HZ);}static int capidrv_addcontr(__u16 contr, struct capi_profile *profp){	capidrv_contr *card;	long flags;	isdn_ctrl cmd;	char id[20];	int i;	MOD_INC_USE_COUNT;	sprintf(id, "capidrv-%d", contr);	if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) {		printk(KERN_WARNING		 "capidrv: (%s) Could not allocate contr-struct.\n", id);		MOD_DEC_USE_COUNT;		return -1;	}	memset(card, 0, sizeof(capidrv_contr));	init_timer(&card->listentimer);	strcpy(card->name, id);	card->contrnr = contr;	card->nbchan = profp->nbchannel;	card->bchans = (capidrv_bchan *) kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC);	if (!card->bchans) {		printk(KERN_WARNING		"capidrv: (%s) Could not allocate bchan-structs.\n", id);		kfree(card);		MOD_DEC_USE_COUNT;		return -1;	}	card->interface.channels = profp->nbchannel;	card->interface.maxbufsize = 2048;	card->interface.command = if_command;	card->interface.writebuf_skb = if_sendbuf;	card->interface.writecmd = 0;	card->interface.readstat = if_readstat;	card->interface.features = ISDN_FEATURE_L2_HDLC |	    			   ISDN_FEATURE_L2_TRANS |	    			   ISDN_FEATURE_L3_TRANS |				   ISDN_FEATURE_P_UNKNOWN |				   ISDN_FEATURE_L2_X75I |				   ISDN_FEATURE_L2_X75UI |				   ISDN_FEATURE_L2_X75BUI;	if (profp->support1 & (1<<2))		card->interface.features |= ISDN_FEATURE_L2_V11096 |	    				    ISDN_FEATURE_L2_V11019 |	    				    ISDN_FEATURE_L2_V11038;	if (profp->support1 & (1<<8))		card->interface.features |= ISDN_FEATURE_L2_MODEM;	card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */	strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);	card->q931_read = card->q931_buf;	card->q931_write = card->q931_buf;	card->q931_end = card->q931_buf + sizeof(card->q931_buf) - 1;	if (!register_isdn(&card->interface)) {		printk(KERN_ERR "capidrv: Unable to register contr %s\n", id);		kfree(card->bchans);		kfree(card);		MOD_DEC_USE_COUNT;		return -1;	}	card->myid = card->interface.channels;	spin_lock_irqsave(&global_lock, flags);	card->next = global.contr_list;	global.contr_list = card;	global.ncontr++;	spin_unlock_irqrestore(&global_lock, flags);	memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan);	for (i = 0; i < card->nbchan; i++) {		card->bchans[i].contr = card;	}	cmd.command = ISDN_STAT_RUN;	cmd.driver = card->myid;	card->i

⌨️ 快捷键说明

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