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

📄 kcapi.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
	unsigned long flags;	spin_lock_irqsave(&notifier_lock, flags);	if (q->head) {		np = q->head;		if ((q->head = np->next) == 0) 			q->tail = 0;		np->next = 0;	}	spin_unlock_irqrestore(&notifier_lock, flags);	return np;}static int notify_push(unsigned int cmd, __u32 controller,				__u16 applid, __u32 ncci){	struct capi_notifier *np;	MOD_INC_USE_COUNT;	np = (struct capi_notifier *)kmalloc(sizeof(struct capi_notifier), GFP_ATOMIC);	if (!np) {		MOD_DEC_USE_COUNT;		return -1;	}	memset(np, 0, sizeof(struct capi_notifier));	np->cmd = cmd;	np->controller = controller;	np->applid = applid;	np->ncci = ncci;	notify_enqueue(np);	/*	 * The notifier will result in adding/deleteing	 * of devices. Devices can only removed in	 * user process, not in bh.	 */	MOD_INC_USE_COUNT;	if (schedule_task(&tq_state_notify) == 0)		MOD_DEC_USE_COUNT;	return 0;}/* -------- KCI_CONTRUP --------------------------------------- */static void notify_up(__u32 contr){	struct capi_interface_user *p;        printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);	spin_lock(&capi_users_lock);	for (p = capi_users; p; p = p->next) {		if (!p->callback) continue;		(*p->callback) (KCI_CONTRUP, contr, &CARD(contr)->profile);	}	spin_unlock(&capi_users_lock);}/* -------- KCI_CONTRDOWN ------------------------------------- */static void notify_down(__u32 contr){	struct capi_interface_user *p;        printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr);	spin_lock(&capi_users_lock);	for (p = capi_users; p; p = p->next) {		if (!p->callback) continue;		(*p->callback) (KCI_CONTRDOWN, contr, 0);	}	spin_unlock(&capi_users_lock);}/* -------- KCI_NCCIUP ---------------------------------------- */static void notify_ncciup(__u32 contr, __u16 applid, __u32 ncci){	struct capi_interface_user *p;	struct capi_ncciinfo n;	n.applid = applid;	n.ncci = ncci;        /*printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);*/	spin_lock(&capi_users_lock);	for (p = capi_users; p; p = p->next) {		if (!p->callback) continue;		(*p->callback) (KCI_NCCIUP, contr, &n);	}	spin_unlock(&capi_users_lock);};/* -------- KCI_NCCIDOWN -------------------------------------- */static void notify_nccidown(__u32 contr, __u16 applid, __u32 ncci){	struct capi_interface_user *p;	struct capi_ncciinfo n;	n.applid = applid;	n.ncci = ncci;        /*printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr);*/	spin_lock(&capi_users_lock);	for (p = capi_users; p; p = p->next) {		if (!p->callback) continue;		(*p->callback) (KCI_NCCIDOWN, contr, &n);	}	spin_unlock(&capi_users_lock);};/* ------------------------------------------------------------ */static void inline notify_doit(struct capi_notifier *np){	switch (np->cmd) {		case KCI_CONTRUP:			notify_up(np->controller);			break;		case KCI_CONTRDOWN:			notify_down(np->controller);			break;		case KCI_NCCIUP:			notify_ncciup(np->controller, np->applid, np->ncci);			break;		case KCI_NCCIDOWN:			notify_nccidown(np->controller, np->applid, np->ncci);			break;	}}static void notify_handler(void *dummy){	struct capi_notifier *np;	while ((np = notify_dequeue()) != 0) {		notify_doit(np);		kfree(np);		MOD_DEC_USE_COUNT;	}	MOD_DEC_USE_COUNT;}	/* -------- NCCI Handling ------------------------------------- */static inline void mq_init(struct capi_ncci * np){	int i;	np->msgidqueue = 0;	np->msgidlast = 0;	np->nmsg = 0;	memset(np->msgidpool, 0, sizeof(np->msgidpool));	np->msgidfree = &np->msgidpool[0];	for (i = 1; i < np->winsize; i++) {		np->msgidpool[i].next = np->msgidfree;		np->msgidfree = &np->msgidpool[i];	}}static inline int mq_enqueue(struct capi_ncci * np, __u16 msgid){	struct msgidqueue *mq;	if ((mq = np->msgidfree) == 0)		return 0;	np->msgidfree = mq->next;	mq->msgid = msgid;	mq->next = 0;	if (np->msgidlast)		np->msgidlast->next = mq;	np->msgidlast = mq;	if (!np->msgidqueue)		np->msgidqueue = mq;	np->nmsg++;	return 1;}static inline int mq_dequeue(struct capi_ncci * np, __u16 msgid){	struct msgidqueue **pp;	for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {		if ((*pp)->msgid == msgid) {			struct msgidqueue *mq = *pp;			*pp = mq->next;			if (mq == np->msgidlast)				np->msgidlast = 0;			mq->next = np->msgidfree;			np->msgidfree = mq;			np->nmsg--;			return 1;		}	}	return 0;}static void controllercb_appl_registered(struct capi_ctr * card, __u16 appl){}static void controllercb_appl_released(struct capi_ctr * card, __u16 appl){	struct capi_ncci **pp, **nextpp;	for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {		if (NCCI2CTRL((*pp)->ncci) == card->cnr) {			struct capi_ncci *np = *pp;			*pp = np->next;			printk(KERN_INFO "kcapi: appl %d ncci 0x%x down!\n", appl, np->ncci);			kfree(np);			APPL(appl)->nncci--;			nextpp = pp;		} else {			nextpp = &(*pp)->next;		}	}	APPL(appl)->releasing--;	if (APPL(appl)->releasing <= 0) {		APPL(appl)->signal = 0;		APPL_MARK_FREE(appl);		printk(KERN_INFO "kcapi: appl %d down\n", appl);	}}/* * ncci managment */static void controllercb_new_ncci(struct capi_ctr * card,					__u16 appl, __u32 ncci, __u32 winsize){	struct capi_ncci *np;	if (!VALID_APPLID(appl)) {		printk(KERN_ERR "avmb1_handle_new_ncci: illegal appl %d\n", appl);		return;	}	if ((np = (struct capi_ncci *) kmalloc(sizeof(struct capi_ncci), GFP_ATOMIC)) == 0) {		printk(KERN_ERR "capi_new_ncci: alloc failed ncci 0x%x\n", ncci);		return;	}	if (winsize > CAPI_MAXDATAWINDOW) {		printk(KERN_ERR "capi_new_ncci: winsize %d too big, set to %d\n",		       winsize, CAPI_MAXDATAWINDOW);		winsize = CAPI_MAXDATAWINDOW;	}	np->applid = appl;	np->ncci = ncci;	np->winsize = winsize;	mq_init(np);	np->next = APPL(appl)->nccilist;	APPL(appl)->nccilist = np;	APPL(appl)->nncci++;	printk(KERN_INFO "kcapi: appl %d ncci 0x%x up\n", appl, ncci);	notify_push(KCI_NCCIUP, CARDNR(card), appl, ncci);}static void controllercb_free_ncci(struct capi_ctr * card,				__u16 appl, __u32 ncci){	struct capi_ncci **pp;	if (!VALID_APPLID(appl)) {		printk(KERN_ERR "free_ncci: illegal appl %d\n", appl);		return;	}	for (pp = &APPL(appl)->nccilist; *pp; pp = &(*pp)->next) {		if ((*pp)->ncci == ncci) {			struct capi_ncci *np = *pp;			*pp = np->next;			kfree(np);			APPL(appl)->nncci--;			printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", appl, ncci);			notify_push(KCI_NCCIDOWN, CARDNR(card), appl, ncci);			return;		}	}	printk(KERN_ERR "free_ncci: ncci 0x%x not found\n", ncci);}static struct capi_ncci *find_ncci(struct capi_appl * app, __u32 ncci){	struct capi_ncci *np;	for (np = app->nccilist; np; np = np->next) {		if (np->ncci == ncci)			return np;	}	return 0;}/* -------- Receiver ------------------------------------------ */static void recv_handler(void *dummy){	struct sk_buff *skb;	while ((skb = skb_dequeue(&recv_queue)) != 0) {		__u16 appl = CAPIMSG_APPID(skb->data);		struct capi_ncci *np;		if (!VALID_APPLID(appl)) {			printk(KERN_ERR "kcapi: recv_handler: applid %d ? (%s)\n",			       appl, capi_message2str(skb->data));			kfree_skb(skb);			continue;		}		if (APPL(appl)->signal == 0) {			printk(KERN_ERR "kcapi: recv_handler: applid %d has no signal function\n",			       appl);			kfree_skb(skb);			continue;		}		if (   CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3		    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF	            && (np = find_ncci(APPL(appl), CAPIMSG_NCCI(skb->data))) != 0		    && mq_dequeue(np, CAPIMSG_MSGID(skb->data)) == 0) {			printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n",				CAPIMSG_MSGID(skb->data), np->ncci);		}		if (   CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3		    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {			APPL(appl)->nrecvdatapkt++;		} else {			APPL(appl)->nrecvctlpkt++;		}		skb_queue_tail(&APPL(appl)->recv_queue, skb);		(APPL(appl)->signal) (APPL(appl)->applid, APPL(appl)->param);	}}static void controllercb_handle_capimsg(struct capi_ctr * card,				__u16 appl, struct sk_buff *skb){	int showctl = 0;	__u8 cmd, subcmd;	if (card->cardstate != CARD_RUNNING) {		printk(KERN_INFO "kcapi: controller %d not active, got: %s",		       card->cnr, capi_message2str(skb->data));		goto error;	}	cmd = CAPIMSG_COMMAND(skb->data);        subcmd = CAPIMSG_SUBCOMMAND(skb->data);	if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) {		card->nrecvdatapkt++;	        if (card->traceflag > 2) showctl |= 2;	} else {		card->nrecvctlpkt++;	        if (card->traceflag) showctl |= 2;	}	showctl |= (card->traceflag & 1);	if (showctl & 2) {		if (showctl & 1) {			printk(KERN_DEBUG "kcapi: got [0x%lx] id#%d %s len=%u\n",			       (unsigned long) card->cnr,			       CAPIMSG_APPID(skb->data),			       capi_cmd2str(cmd, subcmd),			       CAPIMSG_LEN(skb->data));		} else {			printk(KERN_DEBUG "kcapi: got [0x%lx] %s\n",					(unsigned long) card->cnr,					capi_message2str(skb->data));		}	}	skb_queue_tail(&recv_queue, skb);	queue_task(&tq_recv_notify, &tq_immediate);	mark_bh(IMMEDIATE_BH);	return;error:	kfree_skb(skb);}static void controllercb_ready(struct capi_ctr * card){	__u16 appl;	card->cardstate = CARD_RUNNING;	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {		if (!VALID_APPLID(appl)) continue;		if (APPL(appl)->releasing) continue;		card->driver->register_appl(card, appl, &APPL(appl)->rparam);	}        printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n",		CARDNR(card), card->name);	notify_push(KCI_CONTRUP, CARDNR(card), 0, 0);}static void controllercb_reseted(struct capi_ctr * card){	__u16 appl;        if (card->cardstate == CARD_FREE)		return;        if (card->cardstate == CARD_DETECTED)		return;        card->cardstate = CARD_DETECTED;	memset(card->manu, 0, sizeof(card->manu));	memset(&card->version, 0, sizeof(card->version));	memset(&card->profile, 0, sizeof(card->profile));	memset(card->serial, 0, sizeof(card->serial));	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {		struct capi_ncci **pp, **nextpp;		for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {			if (NCCI2CTRL((*pp)->ncci) == card->cnr) {				struct capi_ncci *np = *pp;				*pp = np->next;				printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down!\n", appl, np->ncci);				notify_push(KCI_NCCIDOWN, CARDNR(card), appl, np->ncci);				kfree(np);				nextpp = pp;			} else {				nextpp = &(*pp)->next;			}		}	}	printk(KERN_NOTICE "kcapi: card %d down.\n", CARDNR(card));	notify_push(KCI_CONTRDOWN, CARDNR(card), 0, 0);}static void controllercb_suspend_output(struct capi_ctr *card){	if (!card->blocked) {		printk(KERN_DEBUG "kcapi: card %d suspend\n", CARDNR(card));		card->blocked = 1;	}}static void controllercb_resume_output(struct capi_ctr *card){	if (card->blocked) {		printk(KERN_DEBUG "kcapi: card %d resume\n", CARDNR(card));		card->blocked = 0;	}}/* ------------------------------------------------------------- */struct capi_ctr *drivercb_attach_ctr(struct capi_driver *driver, char *name, void *driverdata){	struct capi_ctr *card, **pp;	int i;	for (i=0; i < CAPI_MAXCONTR && cards[i].cardstate != CARD_FREE; i++) ;   	if (i == CAPI_MAXCONTR) {		printk(KERN_ERR "kcapi: out of controller slots\n");	   	return 0;	}	card = &cards[i];	memset(card, 0, sizeof(struct capi_ctr));	card->driver = driver;	card->cnr = CARDNR(card);	strncpy(card->name, name, sizeof(card->name));	card->cardstate = CARD_DETECTED;	card->blocked = 0;	card->driverdata = driverdata;	card->traceflag = showcapimsgs;        card->ready = controllercb_ready;         card->reseted = controllercb_reseted;         card->suspend_output = controllercb_suspend_output;        card->resume_output = controllercb_resume_output;        card->handle_capimsg = controllercb_handle_capimsg;	card->appl_registered = controllercb_appl_registered;	card->appl_released = controllercb_appl_released;        card->new_ncci = controllercb_new_ncci;        card->free_ncci = controllercb_free_ncci;	for (pp = &driver->controller; *pp; pp = &(*pp)->next) ;	card->next = 0;	*pp = card;	driver->ncontroller++;	sprintf(card->procfn, "capi/controllers/%d", card->cnr);	card->procent = create_proc_entry(card->procfn, 0, 0);	if (card->procent) {	   card->procent->read_proc = 		(int (*)(char *,char **,off_t,int,int *,void *))			driver->ctr_read_proc;	   card->procent->data = card;	}	ncards++;	printk(KERN_NOTICE "kcapi: Controller %d: %s attached\n",			card->cnr, card->name);	return card;}static int drivercb_detach_ctr(struct capi_ctr *card){	struct capi_driver *driver = card->driver;	struct capi_ctr **pp;        if (card->cardstate == CARD_FREE)		return 0;        if (card->cardstate != CARD_DETECTED)		controllercb_reseted(card);	for (pp = &driver->controller; *pp ; pp = &(*pp)->next) {        	if (*pp == card) {	        	*pp = card->next;			driver->ncontroller--;			ncards--;	        	break;		}	}	if (card->procent) {	   remove_proc_entry(card->procfn, 0);	   card->procent = 0;	}	card->cardstate = CARD_FREE;	printk(KERN_NOTICE "kcapi: Controller %d: %s unregistered\n",			card->cnr, card->name);	return 0;}/* ------------------------------------------------------------- *//* fallback if no driver read_proc function defined by driver */static int driver_read_proc(char *page, char **start, off_t off,        		int count, int *eof, void *data){	struct capi_driver *driver = (struct capi_driver *)data;	int len = 0;	len += sprintf(page+len, "%-16s %s\n", "name", driver->name);	len += sprintf(page+len, "%-16s %s\n", "revision", driver->revision);	if (len < off)            return 0;	*eof = 1;	*start = page + off;	return ((count < len-off) ? count : len-off);}/* ------------------------------------------------------------- */static struct capi_driver_interface di = {    drivercb_attach_ctr,    drivercb_detach_ctr,};struct capi_driver_interface *attach_capi_driver(struct capi_driver *driver){	struct capi_driver **pp;	MOD_INC_USE_COUNT;	spin_lock(&drivers_lock);	for (pp = &drivers; *pp; pp = &(*pp)->next) ;	driver->next = 0;	*pp = driver;	spin_unlock(&drivers_lock);	printk(KERN_NOTICE "kcapi: driver %s attached\n", driver->name);	sprintf(driver->procfn, "capi/drivers/%s", driver->name);	driver->procent = create_proc_entry(driver->procfn, 0, 0);	if (driver->procent) {	   if (driver->driver_read_proc) {		   driver->procent->read_proc = 	       		(int (*)(char *,char **,off_t,int,int *,void *))					driver->driver_read_proc;	   } else {		   driver->procent->read_proc = driver_read_proc;	   }	   driver->procent->data = driver;	}	return &di;}void detach_capi_driver(struct capi_driver *driver){	struct capi_driver **pp;	spin_lock(&drivers_lock);	for (pp = &drivers; *pp && *pp != driver; pp = &(*pp)->next) ;	if (*pp) {		*pp = (*pp)->next;		printk(KERN_NOTICE "kcapi: driver %s detached\n", driver->name);	} else {		printk(KERN_ERR "kcapi: driver %s double detach ?\n", driver->name);	}	spin_unlock(&drivers_lock);	if (driver->procent) {	   remove_proc_entry(driver->procfn, 0);	   driver->procent = 0;	}	MOD_DEC_USE_COUNT;}/* ------------------------------------------------------------- *//* -------- CAPI2.0 Interface ---------------------------------- *//* ------------------------------------------------------------- */static __u16 capi_isinstalled(void){	int i;	for (i = 0; i < CAPI_MAXCONTR; i++) {		if (cards[i].cardstate == CARD_RUNNING)			return CAPI_NOERROR;	}	return CAPI_REGNOTINSTALLED;}static __u16 capi_register(capi_register_params * rparam, __u16 * applidp){

⌨️ 快捷键说明

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