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

📄 capidrv.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
}static inline __u8 cip2si1(__u16 cipval){	static const __u8 si[32] =	{7, 1, 7, 7, 1, 1, 7, 7,	/*0-7 */	 7, 1, 0, 0, 0, 0, 0, 0,	/*8-15 */	 1, 2, 4, 10, 9, 9, 15, 7,	/*16-23 */	 7, 7, 1, 16, 16, 0, 0, 0};	/*24-31 */	if (cipval > 31)		cipval = 0;	/* .... */	return si[cipval];}static inline __u8 cip2si2(__u16 cipval){	static const __u8 si[32] =	{0, 0, 0, 0, 2, 3, 0, 0,	/*0-7 */	 0, 3, 0, 0, 0, 0, 0, 0,	/*8-15 */	 1, 2, 0, 0, 9, 0, 0, 0,	/*16-23 */	 0, 0, 3, 2, 3, 0, 0, 0};	/*24-31 */	if (cipval > 31)		cipval = 0;	/* .... */	return si[cipval];}/* -------- controller managment ------------------------------------- */static inline capidrv_contr *findcontrbydriverid(int driverid){    	unsigned long flags;	capidrv_contr *p;	spin_lock_irqsave(&global_lock, flags);	for (p = global.contr_list; p; p = p->next)		if (p->myid == driverid)			break;	spin_unlock_irqrestore(&global_lock, flags);	return p;}static capidrv_contr *findcontrbynumber(__u32 contr){	unsigned long flags;	capidrv_contr *p = global.contr_list;	spin_lock_irqsave(&global_lock, flags);	for (p = global.contr_list; p; p = p->next)		if (p->contrnr == contr)			break;	spin_unlock_irqrestore(&global_lock, flags);	return p;}/* -------- plci management ------------------------------------------ */static capidrv_plci *new_plci(capidrv_contr * card, int chan){	capidrv_plci *plcip;	plcip = (capidrv_plci *) kmalloc(sizeof(capidrv_plci), GFP_ATOMIC);	if (plcip == 0)		return 0;	memset(plcip, 0, sizeof(capidrv_plci));	plcip->state = ST_PLCI_NONE;	plcip->plci = 0;	plcip->msgid = 0;	plcip->chan = chan;	plcip->next = card->plci_list;	card->plci_list = plcip;	card->bchans[chan].plcip = plcip;	return plcip;}static capidrv_plci *find_plci_by_plci(capidrv_contr * card, __u32 plci){	capidrv_plci *p;	for (p = card->plci_list; p; p = p->next)		if (p->plci == plci)			return p;	return 0;}static capidrv_plci *find_plci_by_msgid(capidrv_contr * card, __u16 msgid){	capidrv_plci *p;	for (p = card->plci_list; p; p = p->next)		if (p->msgid == msgid)			return p;	return 0;}static capidrv_plci *find_plci_by_ncci(capidrv_contr * card, __u32 ncci){	capidrv_plci *p;	for (p = card->plci_list; p; p = p->next)		if (p->plci == (ncci & 0xffff))			return p;	return 0;}static void free_plci(capidrv_contr * card, capidrv_plci * plcip){	capidrv_plci **pp;	for (pp = &card->plci_list; *pp; pp = &(*pp)->next) {		if (*pp == plcip) {			*pp = (*pp)->next;			card->bchans[plcip->chan].plcip = 0;			card->bchans[plcip->chan].disconnecting = 0;			card->bchans[plcip->chan].incoming = 0;			kfree(plcip);			return;		}	}	printk(KERN_ERR "capidrv-%d: free_plci %p (0x%x) not found, Huh?\n",	       card->contrnr, plcip, plcip->plci);}/* -------- ncci management ------------------------------------------ */static inline capidrv_ncci *new_ncci(capidrv_contr * card,				     capidrv_plci * plcip,				     __u32 ncci){	capidrv_ncci *nccip;	nccip = (capidrv_ncci *) kmalloc(sizeof(capidrv_ncci), GFP_ATOMIC);	if (nccip == 0)		return 0;	memset(nccip, 0, sizeof(capidrv_ncci));	nccip->ncci = ncci;	nccip->state = ST_NCCI_NONE;	nccip->plcip = plcip;	nccip->chan = plcip->chan;	nccip->datahandle = 0;	nccip->next = plcip->ncci_list;	plcip->ncci_list = nccip;	card->bchans[plcip->chan].nccip = nccip;	return nccip;}static inline capidrv_ncci *find_ncci(capidrv_contr * card, __u32 ncci){	capidrv_plci *plcip;	capidrv_ncci *p;	if ((plcip = find_plci_by_ncci(card, ncci)) == 0)		return 0;	for (p = plcip->ncci_list; p; p = p->next)		if (p->ncci == ncci)			return p;	return 0;}static inline capidrv_ncci *find_ncci_by_msgid(capidrv_contr * card,					       __u32 ncci, __u16 msgid){	capidrv_plci *plcip;	capidrv_ncci *p;	if ((plcip = find_plci_by_ncci(card, ncci)) == 0)		return 0;	for (p = plcip->ncci_list; p; p = p->next)		if (p->msgid == msgid)			return p;	return 0;}static void free_ncci(capidrv_contr * card, struct capidrv_ncci *nccip){	struct capidrv_ncci **pp;	for (pp = &(nccip->plcip->ncci_list); *pp; pp = &(*pp)->next) {		if (*pp == nccip) {			*pp = (*pp)->next;			break;		}	}	card->bchans[nccip->chan].nccip = 0;	kfree(nccip);}static int capidrv_add_ack(struct capidrv_ncci *nccip,		           __u16 datahandle, int len){	struct ncci_datahandle_queue *n, **pp;	n = (struct ncci_datahandle_queue *)		kmalloc(sizeof(struct ncci_datahandle_queue), GFP_ATOMIC);	if (!n) {	   printk(KERN_ERR "capidrv: kmalloc ncci_datahandle failed\n");	   return -1;	}	n->next = 0;	n->datahandle = datahandle;	n->len = len;	for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) ;	*pp = n;	return 0;}static int capidrv_del_ack(struct capidrv_ncci *nccip, __u16 datahandle){	struct ncci_datahandle_queue **pp, *p;	int len;	for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) { 		if ((*pp)->datahandle == datahandle) {			p = *pp;			len = p->len;			*pp = (*pp)->next;		        kfree(p);			return len;		}	}	return -1;}/* -------- convert and send capi message ---------------------------- */static void send_message(capidrv_contr * card, _cmsg * cmsg){	struct sk_buff *skb;	size_t len;	capi_cmsg2message(cmsg, cmsg->buf);	len = CAPIMSG_LEN(cmsg->buf);	skb = alloc_skb(len, GFP_ATOMIC);	memcpy(skb_put(skb, len), cmsg->buf, len);	(*capifuncs->capi_put_message) (global.appid, skb);	global.nsentctlpkt++;}/* -------- state machine -------------------------------------------- */struct listenstatechange {	int actstate;	int nextstate;	int event;};static struct listenstatechange listentable[] ={  {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ},  {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ},  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR},  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR},  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},  {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},  {},};static void listen_change_state(capidrv_contr * card, int event){	struct listenstatechange *p = listentable;	while (p->event) {		if (card->state == p->actstate && p->event == event) {			if (debugmode)				printk(KERN_DEBUG "capidrv-%d: listen_change_state %d -> %d\n",				       card->contrnr, card->state, p->nextstate);			card->state = p->nextstate;			return;		}		p++;	}	printk(KERN_ERR "capidrv-%d: listen_change_state state=%d event=%d ????\n",	       card->contrnr, card->state, event);}/* ------------------------------------------------------------------ */static void p0(capidrv_contr * card, capidrv_plci * plci){	isdn_ctrl cmd;	card->bchans[plci->chan].contr = 0;	cmd.command = ISDN_STAT_DHUP;	cmd.driver = card->myid;	cmd.arg = plci->chan;	card->interface.statcallb(&cmd);	free_plci(card, plci);}/* ------------------------------------------------------------------ */struct plcistatechange {	int actstate;	int nextstate;	int event;	void (*changefunc) (capidrv_contr * card, capidrv_plci * plci);};static struct plcistatechange plcitable[] ={  /* P-0 */  {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, 0},  {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, 0},  {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, 0},  {ST_PLCI_NONE, ST_PLCI_RESUMEING, EV_PLCI_RESUME_REQ, 0},  /* P-0.1 */  {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0},  {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0},  /* P-1 */  {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},  /* P-ACT */  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},  {ST_PLCI_ACTIVE, ST_PLCI_HELD, EV_PLCI_HOLD_IND, 0},  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_SUSPEND_IND, 0},  /* P-2 */  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},  {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, 0},  {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, 0},  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CD_IND, 0},  /* P-3 */  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},  {ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, 0},  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},  /* P-4 */  {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},  /* P-5 */  {ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},  /* P-6 */  {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0},  /* P-0.Res */  {ST_PLCI_RESUMEING, ST_PLCI_NONE, EV_PLCI_RESUME_CONF_ERROR, p0},  {ST_PLCI_RESUMEING, ST_PLCI_RESUME, EV_PLCI_RESUME_CONF_OK, 0},  /* P-RES */  {ST_PLCI_RESUME, ST_PLCI_ACTIVE, EV_PLCI_RESUME_IND, 0},  /* P-HELD */  {ST_PLCI_HELD, ST_PLCI_ACTIVE, EV_PLCI_RETRIEVE_IND, 0},  {},};static void plci_change_state(capidrv_contr * card, capidrv_plci * plci, int event){	struct plcistatechange *p = plcitable;	while (p->event) {		if (plci->state == p->actstate && p->event == event) {			if (debugmode)				printk(KERN_DEBUG "capidrv-%d: plci_change_state:0x%x %d -> %d\n",				  card->contrnr, plci->plci, plci->state, p->nextstate);			plci->state = p->nextstate;			if (p->changefunc)				p->changefunc(card, plci);			return;		}		p++;	}	printk(KERN_ERR "capidrv-%d: plci_change_state:0x%x state=%d event=%d ????\n",	       card->contrnr, plci->plci, plci->state, event);}/* ------------------------------------------------------------------ */static _cmsg cmsg;static void n0(capidrv_contr * card, capidrv_ncci * ncci){	isdn_ctrl cmd;	capi_fill_DISCONNECT_REQ(&cmsg,				 global.appid,				 card->msgid++,				 ncci->plcip->plci,				 0,	/* BChannelinformation */				 0,	/* Keypadfacility */				 0,	/* Useruserdata */   /* $$$$ */				 0	/* Facilitydataarray */	);	send_message(card, &cmsg);	plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ);	cmd.command = ISDN_STAT_BHUP;	cmd.driver = card->myid;	cmd.arg = ncci->chan;	card->interface.statcallb(&cmd);	free_ncci(card, ncci);}/* ------------------------------------------------------------------ */struct nccistatechange {	int actstate;	int nextstate;	int event;	void (*changefunc) (capidrv_contr * card, capidrv_ncci * ncci);};static struct nccistatechange nccitable[] ={  /* N-0 */  {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, 0},  {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, 0},  /* N-0.1 */  {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, 0},  {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, n0},  /* N-1 */  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, 0},  {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, 0},  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},  /* N-2 */  {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, 0},  {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},  {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},  /* N-ACT */  {ST_NCCI_ACTIVE, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},  {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, 0},  {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},  {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},  /* N-3 */  {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},  {ST_NCCI_RESETING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},  {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},  /* N-4 */  {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},  {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR,0},  /* N-5 */  {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0},  {},};static void ncci_change_state(capidrv_contr * card, capidrv_ncci * ncci, int event){	struct nccistatechange *p = nccitable;	while (p->event) {		if (ncci->state == p->actstate && p->event == event) {			if (debugmode)				printk(KERN_DEBUG "capidrv-%d: ncci_change_state:0x%x %d -> %d\n",				  card->contrnr, ncci->ncci, ncci->state, p->nextstate);			if (p->nextstate == ST_NCCI_PREVIOUS) {

⌨️ 快捷键说明

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