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

📄 capidrv.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 = capi20_put_message(&global.ap, nskb);		if (errcode == CAPI_NOERROR) {			dev_kfree_skb(skb);			nccip->datahandle++;			return len;		}		if (debugmode > 3)			printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n",				card->contrnr, errcode, capi_info2str(errcode));	        (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 = capi20_put_message(&global.ap, skb);		if (errcode == CAPI_NOERROR) {			nccip->datahandle++;			return len;		}		if (debugmode > 3)			printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n",				card->contrnr, errcode, capi_info2str(errcode));		skb_pull(skb, msglen);	        (void)capidrv_del_ack(nccip, datahandle);		return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;	}}static int if_readstat(u8 __user *buf, int len, int id, int channel){	capidrv_contr *card = findcontrbydriverid(id);	int count;	u8 __user *p;	if (!card) {		printk(KERN_ERR "capidrv: if_readstat called with invalid driverId %d!\n",		       id);		return -ENODEV;	}	for (p=buf, count=0; count < len; p++, count++) {		put_user(*card->q931_read++, p);	        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 = capi20_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 = capi20_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.ap.applid,					   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.ap.applid,					   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.ap.applid,			     card->msgid++,			     card->contrnr, /* controller */			     1 << 6,	/* Infomask */			     card->cipmask,			     card->cipmask2,			     NULL, NULL);	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;	unsigned long flags;	isdn_ctrl cmd;	char id[20];	int i;	sprintf(id, "capidrv-%d", contr);	if (!try_module_get(THIS_MODULE)) {		printk(KERN_WARNING "capidrv: (%s) Could not reserve module\n", id);		return -1;	}	if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) {		printk(KERN_WARNING		 "capidrv: (%s) Could not allocate contr-struct.\n", id);		return -1;	}	memset(card, 0, sizeof(capidrv_contr));	card->owner = THIS_MODULE;	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);		module_put(card->owner);		kfree(card);		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 = NULL;	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);		module_put(card->owner);		kfree(card);		return -1;	}	card->myid = card->interface.channels;	memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan);	for (i = 0; i < card->nbchan; i++) {		card->bchans[i].contr = card;	}	spin_lock_irqsave(&global_lock, flags);	card->next = global.contr_list;	global.contr_list = card;	global.ncontr++;	spin_unlock_irqrestore(&global_lock, flags);	cmd.command = ISDN_STAT_RUN;	cmd.driver = card->myid;	card->interface.statcallb(&cmd);	card->cipmask = 0x1FFF03FF;	/* any */	card->cipmask2 = 0;	card->listentimer.data = (unsigned long)card;	card->listentimer.function = listentimerfunc;	send_listen(card);	mod_timer(&card->listentimer, jiffies + 60*HZ);	printk(KERN_INFO "%s: now up (%d B channels)\n",		card->name, card->nbchan);	enable_dchannel_trace(card);	return 0;}static int capidrv_delcontr(u16 contr){	capidrv_contr **pp, *card;	unsigned long flags;	isdn_ctrl cmd;	spin_lock_irqsave(&global_lock, flags);	for (card = global.contr_list; card; card = card->next) {		if (card->contrnr == contr)			break;	}	if (!card) {		spin_unlock_irqrestore(&global_lock, flags);		printk(KERN_ERR "capidrv: delcontr: no contr %u\n", contr);		return -1;	}	#warning FIXME: maybe a race condition the card should be removed here from global list /kkeil	spin_unlock_irqrestore(&global_lock, flags);	del_timer(&card->listentimer);	if (debugmode)		printk(KERN_DEBUG "capidrv-%d: id=%d unloading\n",					card->contrnr, card->myid);	cmd.command = ISDN_STAT_STOP;	cmd.driver = card->myid;	card->interface.statcallb(&cmd);	while (card->nbchan) {		cmd.command = ISDN_STAT_DISCH;		cmd.driver = card->myid;		cmd.arg = card->nbchan-1;	        cmd.parm.num[0] = 0;		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: id=%d disable chan=%ld\n",					card->contrnr, card->myid, cmd.arg);		card->interface.statcallb(&cmd);		if (card->bchans[card->nbchan-1].nccip)			free_ncci(card, card->bchans[card->nbchan-1].nccip);		if (card->bchans[card->nbchan-1].plcip)			free_plci(card, card->bchans[card->nbchan-1].plcip);		if (card->plci_list)			printk(KERN_ERR "capidrv: bug in free_plci()\n");		card->nbchan--;	}	kfree(card->bchans);	card->bchans = NULL;	if (debugmode)		printk(KERN_DEBUG "capidrv-%d: id=%d isdn unload\n",					card->contrnr, card->myid);	cmd.command = ISDN_STAT_UNLOAD;	cmd.driver = card->myid;	card->interface.statcallb(&cmd);	if (debugmode)		printk(KERN_DEBUG "capidrv-%d: id=%d remove contr from list\n",					card->contrnr, card->myid);	spin_lock_irqsave(&global_lock, flags);	for (pp = &global.contr_list; *pp; pp = &(*pp)->next) {		if (*pp == card) {			*pp = (*pp)->next;			card->next = NULL;			global.ncontr--;			break;		}	}	spin_unlock_irqrestore(&global_lock, flags);	module_put(card->owner);	printk(KERN_INFO "%s: now down.\n", card->name);	kfree(card);	return 0;}static void lower_callback(unsigned int cmd, u32 contr, void *data){	switch (cmd) {	case KCI_CONTRUP:		printk(KERN_INFO "capidrv: controller %hu up\n", contr);		(void) capidrv_addcontr(contr, (capi_profile *) data);		break;	case KCI_CONTRDOWN:		printk(KERN_INFO "capidrv: controller %hu down\n", contr);		(void) capidrv_delcontr(contr);		break;	}}/* * /proc/capi/capidrv: * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt */static int proc_capidrv_read_proc(char *page, char **start, off_t off,                                       int count, int *eof, void *data){	int len = 0;	len += sprintf(page+len, "%lu %lu %lu %lu\n",			global.ap.nrecvctlpkt,			global.ap.nrecvdatapkt,			global.ap.nsentctlpkt,			global.ap.nsentdatapkt);	if (off+count >= len)	   *eof = 1;	if (len < off)           return 0;	*start = page + off;	return ((count < len-off) ? count : len-off);}static struct procfsentries {  char *name;  mode_t mode;  int (*read_proc)(char *page, char **start, off_t off,                                       int count, int *eof, void *data);  struct proc_dir_entry *procent;} procfsentries[] = {   /* { "capi",		  S_IFDIR, 0 }, */   { "capi/capidrv", 	  0	 , proc_capidrv_read_proc },};static void __init proc_init(void){    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);    int i;    for (i=0; i < nelem; i++) {        struct procfsentries *p = procfsentries + i;	p->procent = create_proc_entry(p->name, p->mode, NULL);	if (p->procent) p->procent->read_proc = p->read_proc;    }}static void __exit proc_exit(void){    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);    int i;    for (i=nelem-1; i >= 0; i--) {        struct procfsentries *p = procfsentries + i;	if (p->procent) {	   remove_proc_entry(p->name, NULL);	   p->procent = NULL;	}    }}static int __init capidrv_init(void){	capi_profile profile;	char rev[32];	char *p;	u32 ncontr, contr;	u16 errcode;	if ((p = strchr(revision, ':')) != 0 && p[1]) {		strncpy(rev, p + 2, sizeof(rev));		rev[sizeof(rev)-1] = 0;		if ((p = strchr(rev, '$')) != 0 && p > rev)		   *(p-1) = 0;	} else		strcpy(rev, "1.0");	global.ap.rparam.level3cnt = -2;  /* number of bchannels twice */	global.ap.rparam.datablkcnt = 16;	global.ap.rparam.datablklen = 2048;	global.ap.recv_message = capidrv_recv_message;	errcode = capi20_register(&global.ap);	if (errcode) {		return -EIO;	}	capi20_set_callback(&global.ap, lower_callback);	errcode = capi20_get_profile(0, &profile);	if (errcode != CAPI_NOERROR) {		capi20_release(&global.ap);		return -EIO;	}	ncontr = profile.ncontroller;	for (contr = 1; contr <= ncontr; contr++) {		errcode = capi20_get_profile(contr, &profile);		if (errcode != CAPI_NOERROR)			continue;		(void) capidrv_addcontr(contr, &profile);	}	proc_init();	printk(KERN_NOTICE "capidrv: Rev %s: loaded\n", rev);	return 0;}static void __exit capidrv_exit(void){	char rev[10];	char *p;	if ((p = strchr(revision, ':')) != 0) {		strcpy(rev, p + 1);		p = strchr(rev, '$');		*p = 0;	} else {		strcpy(rev, " ??? ");	}	capi20_release(&global.ap);	proc_exit();	printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev);}module_init(capidrv_init);module_exit(capidrv_exit);

⌨️ 快捷键说明

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