static void b1dma_dispatch_tx(avmcard *card)
{
	avmcard_dmainfo *dma = card->dma;
	struct sk_buff *skb;
	u8 cmd, subcmd;
	u16 len;
	u32 txlen;
	void *p;

	skb = skb_dequeue(&dma->send_queue);

	len = CAPIMSG_LEN(skb->data);

	if (len) {
		cmd = CAPIMSG_COMMAND(skb->data);
		subcmd = CAPIMSG_SUBCOMMAND(skb->data);

		p = dma->sendbuf.dmabuf;

		if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
			u16 dlen = CAPIMSG_DATALEN(skb->data);
			_put_byte(&p, SEND_DATA_B3_REQ);
			_put_slice(&p, skb->data, len);
			_put_slice(&p, skb->data + len, dlen);
		} else {
			_put_byte(&p, SEND_MESSAGE);
			_put_slice(&p, skb->data, len);
		}
		txlen = (u8 *)p - (u8 *)dma->sendbuf.dmabuf;
#ifdef AVM_B1DMA_DEBUG
		printk(KERN_DEBUG "tx: put msg len=%d\n", txlen);
#endif
	} else {
		txlen = skb->len - 2;
#ifdef AVM_B1DMA_POLLDEBUG
		if (skb->data[2] == SEND_POLLACK)
			printk(KERN_INFO "%s: send ack\n", card->name);
#endif
#ifdef AVM_B1DMA_DEBUG
		printk(KERN_DEBUG "tx: put 0x%x len=%d\n",
		       skb->data[2], txlen);
#endif
		skb_copy_from_linear_data_offset(skb, 2, dma->sendbuf.dmabuf,
						 skb->len - 2);
	}
	txlen = (txlen + 3) & ~3;

	b1dma_writel(card, dma->sendbuf.dmaaddr, AMCC_TXPTR);
	b1dma_writel(card, txlen, AMCC_TXLEN);

	card->csr |= EN_TX_TC_INT;

	dev_kfree_skb_any(skb);
}
Exemple #2
0
void B1_send_message(unsigned short port, struct sk_buff *skb)
{
	unsigned long flags;
	__u16 len = CAPIMSG_LEN(skb->data);
	__u8 cmd = CAPIMSG_COMMAND(skb->data);
	__u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
	__u32 contr = CAPIMSG_CONTROL(skb->data);

	if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
		__u16 dlen = CAPIMSG_DATALEN(skb->data);

		if (showcapimsgs > 2) {
			if (showcapimsgs & 1) {
				printk(KERN_DEBUG "b1lli: Put [0x%lx] id#%d %s len=%u\n",
				       (unsigned long) contr,
				       CAPIMSG_APPID(skb->data),
				       capi_cmd2str(cmd, subcmd), len);
			} else {
				printk(KERN_DEBUG "b1lli: Put [0x%lx] %s\n",
						(unsigned long) contr,
						capi_message2str(skb->data));
			}

		}
		save_flags(flags);
		cli();
		B1_put_byte(port, SEND_DATA_B3_REQ);
		B1_put_slice(port, skb->data, len);
		B1_put_slice(port, skb->data + len, dlen);
		restore_flags(flags);
	} else {
		if (showcapimsgs) {

			if (showcapimsgs & 1) {
				printk(KERN_DEBUG "b1lli: Put [0x%lx] id#%d %s len=%u\n",
				       (unsigned long) contr,
				       CAPIMSG_APPID(skb->data),
				       capi_cmd2str(cmd, subcmd), len);
			} else {
				printk(KERN_DEBUG "b1lli: Put [0x%lx] %s\n", (unsigned long)contr, capi_message2str(skb->data));
			}
		}
		save_flags(flags);
		cli();
		B1_put_byte(port, SEND_MESSAGE);
		B1_put_slice(port, skb->data, len);
		restore_flags(flags);
	}
	dev_kfree_skb(skb, FREE_WRITE);
}
Exemple #3
0
static void c4_dispatch_tx(avmcard *card)
{
	avmcard_dmainfo *dma = card->dma;
	struct sk_buff *skb;
	u8 cmd, subcmd;
	u16 len;
	u32 txlen;
	void *p;


	if (card->csr & DBELL_DOWN_ARM) { /* tx busy */
		return;
	}

	skb = skb_dequeue(&dma->send_queue);
	if (!skb) {
#ifdef AVM_C4_DEBUG
		printk(KERN_DEBUG "%s: tx underrun\n", card->name);
#endif
		return;
	}

	len = CAPIMSG_LEN(skb->data);

	if (len) {
		cmd = CAPIMSG_COMMAND(skb->data);
		subcmd = CAPIMSG_SUBCOMMAND(skb->data);

		p = dma->sendbuf.dmabuf;

		if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
			u16 dlen = CAPIMSG_DATALEN(skb->data);
			_put_byte(&p, SEND_DATA_B3_REQ);
			_put_slice(&p, skb->data, len);
			_put_slice(&p, skb->data + len, dlen);
		} else {
			_put_byte(&p, SEND_MESSAGE);
			_put_slice(&p, skb->data, len);
		}
		txlen = (u8 *)p - (u8 *)dma->sendbuf.dmabuf;
#ifdef AVM_C4_DEBUG
		printk(KERN_DEBUG "%s: tx put msg len=%d\n", card->name, txlen);
#endif
	} else {
		txlen = skb->len-2;
#ifdef AVM_C4_POLLDEBUG
		if (skb->data[2] == SEND_POLLACK)
			printk(KERN_INFO "%s: ack to c4\n", card->name);
#endif
#ifdef AVM_C4_DEBUG
		printk(KERN_DEBUG "%s: tx put 0x%x len=%d\n",
				card->name, skb->data[2], txlen);
#endif
		skb_copy_from_linear_data_offset(skb, 2, dma->sendbuf.dmabuf,
						 skb->len - 2);
	}
	txlen = (txlen + 3) & ~3;

	c4outmeml(card->mbase+MBOX_DOWN_ADDR, dma->sendbuf.dmaaddr);
	c4outmeml(card->mbase+MBOX_DOWN_LEN, txlen);

	card->csr |= DBELL_DOWN_ARM;

	c4outmeml(card->mbase+DOORBELL, DBELL_DOWN_ARM);

	dev_kfree_skb_any(skb);
}
Exemple #4
0
static void b1dma_dispatch_tx(avmcard *card)
{
	avmcard_dmainfo *dma = card->dma;
	unsigned long flags;
	struct sk_buff *skb;
	__u8 cmd, subcmd;
	__u16 len;
	__u32 txlen;
	int inint;
	void *p;
	
	save_flags(flags);
	cli();

	inint = card->interrupt;

	if (card->csr & EN_TX_TC_INT) { /* tx busy */
	        restore_flags(flags);
		return;
	}

	skb = skb_dequeue(&dma->send_queue);
	if (!skb) {
#ifdef CONFIG_B1DMA_DEBUG
		printk(KERN_DEBUG "tx(%d): underrun\n", inint);
#endif
	        restore_flags(flags);
		return;
	}

	len = CAPIMSG_LEN(skb->data);

	if (len) {
		cmd = CAPIMSG_COMMAND(skb->data);
		subcmd = CAPIMSG_SUBCOMMAND(skb->data);

		p = dma->sendbuf;

		if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
			__u16 dlen = CAPIMSG_DATALEN(skb->data);
			_put_byte(&p, SEND_DATA_B3_REQ);
			_put_slice(&p, skb->data, len);
			_put_slice(&p, skb->data + len, dlen);
		} else {
			_put_byte(&p, SEND_MESSAGE);
			_put_slice(&p, skb->data, len);
		}
		txlen = (__u8 *)p - (__u8 *)dma->sendbuf;
#ifdef CONFIG_B1DMA_DEBUG
		printk(KERN_DEBUG "tx(%d): put msg len=%d\n",
				inint, txlen);
#endif
	} else {
		txlen = skb->len-2;
#ifdef CONFIG_B1DMA_POLLDEBUG
		if (skb->data[2] == SEND_POLLACK)
			printk(KERN_INFO "%s: send ack\n", card->name);
#endif
#ifdef CONFIG_B1DMA_DEBUG
		printk(KERN_DEBUG "tx(%d): put 0x%x len=%d\n",
				inint, skb->data[2], txlen);
#endif
		memcpy(dma->sendbuf, skb->data+2, skb->len-2);
	}
	txlen = (txlen + 3) & ~3;

	b1dmaoutmeml(card->mbase+AMCC_TXPTR, virt_to_phys(dma->sendbuf));
	b1dmaoutmeml(card->mbase+AMCC_TXLEN, txlen);

	card->csr |= EN_TX_TC_INT;

	if (!inint)
		b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);

	restore_flags(flags);
	dev_kfree_skb_any(skb);
}
Exemple #5
0
static void c4_dispatch_tx(avmcard *card)
{
	avmcard_dmainfo *dma = card->dma;
	unsigned long flags;
	struct sk_buff *skb;
	__u8 cmd, subcmd;
	__u16 len;
	__u32 txlen;
	void *p;
	
	save_flags(flags);
	cli();

	if (card->csr & DBELL_DOWN_ARM) { /* tx busy */
	        restore_flags(flags);
		return;
	}

	skb = skb_dequeue(&dma->send_queue);
	if (!skb) {
#ifdef CONFIG_C4_DEBUG
		printk(KERN_DEBUG "%s: tx underrun\n", card->name);
#endif
	        restore_flags(flags);
		return;
	}

	len = CAPIMSG_LEN(skb->data);

	if (len) {
		cmd = CAPIMSG_COMMAND(skb->data);
		subcmd = CAPIMSG_SUBCOMMAND(skb->data);

		p = dma->sendbuf;

		if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
			__u16 dlen = CAPIMSG_DATALEN(skb->data);
			_put_byte(&p, SEND_DATA_B3_REQ);
			_put_slice(&p, skb->data, len);
			_put_slice(&p, skb->data + len, dlen);
		} else {
			_put_byte(&p, SEND_MESSAGE);
			_put_slice(&p, skb->data, len);
		}
		txlen = (__u8 *)p - (__u8 *)dma->sendbuf;
#ifdef CONFIG_C4_DEBUG
		printk(KERN_DEBUG "%s: tx put msg len=%d\n", card->name, txlen);
#endif
	} else {
		txlen = skb->len-2;
#ifdef CONFIG_C4_POLLDEBUG
		if (skb->data[2] == SEND_POLLACK)
			printk(KERN_INFO "%s: ack to c4\n", card->name);
#endif
#ifdef CONFIG_C4_DEBUG
		printk(KERN_DEBUG "%s: tx put 0x%x len=%d\n",
				card->name, skb->data[2], txlen);
#endif
		memcpy(dma->sendbuf, skb->data+2, skb->len-2);
	}
	txlen = (txlen + 3) & ~3;

	c4outmeml(card->mbase+MBOX_DOWN_ADDR, virt_to_phys(dma->sendbuf));
	c4outmeml(card->mbase+MBOX_DOWN_LEN, txlen);

	card->csr |= DBELL_DOWN_ARM;

	c4outmeml(card->mbase+DOORBELL, DBELL_DOWN_ARM);

	restore_flags(flags);
	dev_kfree_skb_any(skb);
}
static void handle_controller(capiconn_context *ctx, _cmsg * cmsg)
{
	capi_contr *card = findcontrbynumber(ctx, cmsg->adr.adrController&0x7f);
	capiconn_callbacks *cb = ctx->cb;

	if (!card) {
		(*cb->errmsg)("capiconn: %s from unknown controller 0x%x",
		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
		       cmsg->adr.adrController & 0x7f);
		return;
	}
	switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {

	case CAPI_LISTEN_CONF:	/* Controller */
		(*cb->debugmsg)("contr %d: listenconf Info=0x%04x (%s) infomask=0x%x cipmask=0x%x capimask2=0x%x",
			       card->contrnr, cmsg->Info,
			       capi_info2str(cmsg->Info),
			       card->infomask,
			       card->cipmask,
			       card->cipmask2);
		if (cmsg->Info) {
			listen_change_state(card, EV_LISTEN_CONF_ERROR);
		} else if (card->cipmask == 0) {
			listen_change_state(card, EV_LISTEN_CONF_EMPTY);
		} else {
			listen_change_state(card, EV_LISTEN_CONF_OK);
		}
		break;

	case CAPI_MANUFACTURER_IND:	/* Controller */
#if 0
		if (   cmsg->ManuID == 0x214D5641
		    && cmsg->Class == 0
		    && cmsg->Function == 1) {
		   _cbyte *data = cmsg->ManuData+3;
		   _cword len = cmsg->ManuData[0];
		   _cword layer;
		   int direction;
		   if (len == 255) {
		      len = (cmsg->ManuData[1] | (cmsg->ManuData[2] << 8));
		      data += 2;
		   }
		   len -= 2;
		   layer = ((*(data-1)) << 8) | *(data-2);
		   if (layer & 0x300)
			direction = (layer & 0x200) ? 0 : 1;
		   else direction = (layer & 0x800) ? 0 : 1;
		   if (layer & 0x0C00) {
		   	if ((layer & 0xff) == 0x80) {
		           handle_dtrace_data(card, direction, 1, data, len);
		           break;
		   	}
		   } else if ((layer & 0xff) < 0x80) {
		      handle_dtrace_data(card, direction, 0, data, len);
		      break;
		   }
	           (*cb->infomsg)("%s from controller %d layer 0x%x, ignored",
			capi_cmd2str(cmsg->Command, cmsg->Subcommand),
			cmsg->adr.adrController, layer);
                   break;
		}
#endif
		goto ignored;
	case CAPI_MANUFACTURER_CONF:	/* Controller */
		if (cmsg->ManuID == 0x214D5641) {
		   char *s = 0;
		   switch (cmsg->Class) {
		      case 0: break;
		      case 1: s = "unknown class"; break;
		      case 2: s = "unknown function"; break;
		      default: s = "unkown error"; break;
		   }
		   if (s)
	           (*cb->infomsg)("%s from controller 0x%x function %d: %s",
			capi_cmd2str(cmsg->Command, cmsg->Subcommand),
			cmsg->adr.adrController,
			cmsg->Function, s);
		   break;
		}
		goto ignored;
	case CAPI_FACILITY_IND:	/* Controller/plci/ncci */
		goto ignored;
	case CAPI_FACILITY_CONF:	/* Controller/plci/ncci */
		goto ignored;
	case CAPI_INFO_IND:	/* Controller/plci */
		goto ignored;
	case CAPI_INFO_CONF:	/* Controller/plci */
		goto ignored;

	default:
		(*cb->errmsg)("got %s from controller 0x%x ???",
		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
		       cmsg->adr.adrController);
	}
	return;

      ignored:
	(*cb->infomsg)("%s from controller 0x%x ignored",
	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
	       cmsg->adr.adrController);
}
static void handle_ncci(capiconn_context *ctx, _cmsg * cmsg)
{
	capi_contr *card = findcontrbynumber(ctx, cmsg->adr.adrController&0x7f);
	capiconn_callbacks *cb = ctx->cb;
	capi_connection *plcip;
	capi_ncci *nccip;
	unsigned char *data;

	if (!card) {
		(*cb->errmsg)("capidrv: %s from unknown controller 0x%x",
		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
		       cmsg->adr.adrController & 0x7f);
		return;
	}
	switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {

	case CAPI_CONNECT_B3_ACTIVE_IND:	/* ncci */
		if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
			goto notfound;

		capi_cmsg_answer(cmsg);
		send_message(card, cmsg);
		ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_ACTIVE_IND);


		(*cb->debugmsg)("ncci 0x%x up", nccip->ncci);

		(*cb->connected)(nccip->plcip, cmsg->NCPI);
		break;

	case CAPI_CONNECT_B3_ACTIVE_CONF:	/* ncci */
		goto ignored;

	case CAPI_CONNECT_B3_IND:	/* ncci */

		plcip = find_plci_by_ncci(card, cmsg->adr.adrNCCI);
		if (plcip) {
			nccip = new_ncci(card, plcip, cmsg->adr.adrNCCI);
			if (nccip) {
				ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_IND);
				capi_fill_CONNECT_B3_RESP(cmsg,
							  ctx->appid,
							  card->msgid++,
							  nccip->ncci,	/* adr */
							  0,	/* Reject */
							  0	/* NCPI */
				);
				send_message(card, cmsg);
				ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP);
				break;
			}
			(*cb->errmsg)("capidrv-%d: no mem for ncci, sorry",							card->contrnr);
		} else {
			(*cb->errmsg)("capidrv-%d: %s: plci for ncci 0x%x not found",
			   card->contrnr,
			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
			       cmsg->adr.adrNCCI);
		}
		capi_fill_CONNECT_B3_RESP(cmsg,
					  ctx->appid,
					  card->msgid++,
					  cmsg->adr.adrNCCI,
					  2,	/* Reject */
					  plcip->conninfo.ncpi);
		send_message(card, cmsg);
		break;

	case CAPI_CONNECT_B3_CONF:	/* ncci */

		if (!(nccip = find_ncci_by_msgid(card,
						 cmsg->adr.adrNCCI,
						 cmsg->Messagenumber)))
			goto notfound;

		nccip->ncci = cmsg->adr.adrNCCI;
		nccip->plcip->ncci = cmsg->adr.adrNCCI;
		if (cmsg->Info) {
			(*cb->infomsg)("%s info 0x%x (%s) for ncci 0x%x",
			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
			       cmsg->Info, capi_info2str(cmsg->Info), 
			       cmsg->adr.adrNCCI);
		}

		if (cmsg->Info)
			ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_ERROR);
		else
			ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_OK);
		break;

	case CAPI_CONNECT_B3_T90_ACTIVE_IND:	/* ncci */
		capi_cmsg_answer(cmsg);
		send_message(card, cmsg);
		break;

	case CAPI_DATA_B3_IND:	/* ncci */
		/* handled in handle_data() */
		goto ignored;

	case CAPI_DATA_B3_CONF:	/* ncci */
		if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
			goto notfound;

		data = capi_del_ack(nccip, cmsg->DataHandle);
		if (data == 0)
			break;
		if (cb->datasent)
			(*cb->datasent)(nccip->plcip, data);
		break;

	case CAPI_DISCONNECT_B3_IND:	/* ncci */
		if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
			goto notfound;

		nccip->plcip->disconnectreason_b3 = cmsg->Reason_B3;
		nccip->plcip->disconnecting = 1;
		ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND);
		capi_cmsg_answer(cmsg);
		send_message(card, cmsg);
		ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP);
		break;

	case CAPI_DISCONNECT_B3_CONF:	/* ncci */
		if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
			goto notfound;
		if (cmsg->Info) {
			(*cb->infomsg)("%s info 0x%x (%s) for ncci 0x%x",
			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
			       cmsg->Info, capi_info2str(cmsg->Info), 
			       cmsg->adr.adrNCCI);
			ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_CONF_ERROR);
		}
		break;

	case CAPI_RESET_B3_IND:	/* ncci */
		if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
			goto notfound;
		ncci_change_state(card, nccip, EV_NCCI_RESET_B3_IND);
		capi_cmsg_answer(cmsg);
		send_message(card, cmsg);
		break;

	case CAPI_RESET_B3_CONF:	/* ncci */
		goto ignored;	/* $$$$ */

	case CAPI_FACILITY_IND:	/* Controller/plci/ncci */
		goto ignored;
	case CAPI_FACILITY_CONF:	/* Controller/plci/ncci */
		goto ignored;

	default:
		(*cb->errmsg)("capidrv-%d: got %s for ncci 0x%x ???",
		       card->contrnr,
		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
		       cmsg->adr.adrNCCI);
	}
	return;
ignored:
	(*cb->infomsg)("%s for ncci 0x%x ignored",
	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
	       cmsg->adr.adrNCCI);
	return;
notfound:
	(*cb->errmsg)("%s: ncci 0x%x not found",
	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
	       cmsg->adr.adrNCCI);
}
static void handle_plci(capiconn_context *ctx, _cmsg * cmsg)
{
	capi_contr *card = findcontrbynumber(ctx, cmsg->adr.adrController&0x7f);
	capiconn_callbacks *cb = ctx->cb;
	capi_connection *plcip;

	if (!card) {
		(*cb->errmsg)("capiconn: %s from unknown controller 0x%x",
		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
		       cmsg->adr.adrController & 0x7f);
		return;
	}
	switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {

	case CAPI_DISCONNECT_IND:	/* plci */
		if (cmsg->Reason) {
			(*cb->debugmsg)("%s reason 0x%x (%s) for plci 0x%x",
			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
			       cmsg->Reason, capi_info2str(cmsg->Reason), cmsg->adr.adrPLCI);
		}
		if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI))) {
			capi_cmsg_answer(cmsg);
			send_message(card, cmsg);
			goto notfound;
		}
		plcip->disconnectreason = cmsg->Reason;
		plcip->disconnecting = 1;
		plci_change_state(card, plcip, EV_PLCI_DISCONNECT_IND);
		capi_cmsg_answer(cmsg);
		send_message(card, cmsg);
		plci_change_state(card, plcip, EV_PLCI_DISCONNECT_RESP);
		break;

	case CAPI_DISCONNECT_CONF:	/* plci */
		if (cmsg->Info) {
			(*cb->infomsg)("%s info 0x%x (%s) for plci 0x%x",
			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
			       cmsg->Info, capi_info2str(cmsg->Info), 
			       cmsg->adr.adrPLCI);
		}
		if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
			goto notfound;

		plcip->disconnecting = 1;
		break;

	case CAPI_ALERT_CONF:	/* plci */
		if (cmsg->Info) {
			(*cb->infomsg)("%s info 0x%x (%s) for plci 0x%x",
			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
			       cmsg->Info, capi_info2str(cmsg->Info), 
			       cmsg->adr.adrPLCI);
		}
		break;

	case CAPI_CONNECT_IND:	/* plci */
		handle_incoming_call(card, cmsg);
		break;

	case CAPI_CONNECT_CONF:	/* plci */
		if (cmsg->Info) {
			(*cb->infomsg)("%s info 0x%x (%s) for plci 0x%x",
			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
			       cmsg->Info, capi_info2str(cmsg->Info), 
			       cmsg->adr.adrPLCI);
		}
		if (!(plcip = find_plci_by_msgid(card, cmsg->Messagenumber)))
			goto notfound;

		plcip->plci = cmsg->adr.adrPLCI;
		if (cmsg->Info) {
			plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_ERROR);
		} else {
			plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_OK);
		}
		break;

	case CAPI_CONNECT_ACTIVE_IND:	/* plci */

		if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
			goto notfound;

		if (plcip->incoming) {
			capi_cmsg_answer(cmsg);
			send_message(card, cmsg);
			plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
		} else {
			capi_ncci *nccip;
			capi_cmsg_answer(cmsg);
			send_message(card, cmsg);

			nccip = new_ncci(card, plcip, cmsg->adr.adrPLCI);

			if (!nccip) {
				(*cb->errmsg)("no mem for ncci on contr %d, sorry", card->contrnr);
				break;	/* $$$$ */
			}
			capi_fill_CONNECT_B3_REQ(cmsg,
						 ctx->appid,
						 card->msgid++,
						 plcip->plci,	/* adr */
						 plcip->conninfo.ncpi);
			nccip->msgid = cmsg->Messagenumber;
			send_message(card, cmsg);
			plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
			ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ);
		}
		break;

	case CAPI_INFO_IND:	/* Controller/plci */

		if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
			goto notfound;

		if (handle_charge_info(plcip, cmsg)) {
			capi_cmsg_answer(cmsg);
			send_message(card, cmsg);
		} else if (handle_callednumber_info(plcip, cmsg)) {
			capi_cmsg_answer(cmsg);
			send_message(card, cmsg);
		} else {
			capi_cmsg_answer(cmsg);
			send_message(card, cmsg);
		}
		break;

	case CAPI_CONNECT_ACTIVE_CONF:		/* plci */
		goto ignored;
	case CAPI_SELECT_B_PROTOCOL_CONF:	/* plci */
		goto ignored;
	case CAPI_FACILITY_IND:	/* Controller/plci/ncci */
		goto ignored;
	case CAPI_FACILITY_CONF:	/* Controller/plci/ncci */
		goto ignored;
	case CAPI_INFO_CONF:	/* Controller/plci */
		goto ignored;

	default:
		(*cb->errmsg)("got %s for plci 0x%x ???",
		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
		       cmsg->adr.adrPLCI);
	}
	return;

ignored:
	(*cb->infomsg)("%s for plci 0x%x ignored",
	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
	       cmsg->adr.adrPLCI);
	return;

notfound:
	(*cb->errmsg)("%s: plci 0x%x not found",
	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
	       cmsg->adr.adrPLCI);
	return;
}