Ejemplo n.º 1
0
static int
isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
{
	struct bchannel *bch = container_of(ch, struct bchannel, ch);
	struct isar_ch *ich = container_of(bch, struct isar_ch, bch);
	int ret = -EINVAL;
	u_long flags;

	pr_debug("%s: %s cmd:%x %p\n", ich->is->name, __func__, cmd, arg);
	switch (cmd) {
	case CLOSE_CHANNEL:
		test_and_clear_bit(FLG_OPEN, &bch->Flags);
		cancel_work_sync(&bch->workq);
		spin_lock_irqsave(ich->is->hwlock, flags);
		mISDN_clear_bchannel(bch);
		modeisar(ich, ISDN_P_NONE);
		spin_unlock_irqrestore(ich->is->hwlock, flags);
		ch->protocol = ISDN_P_NONE;
		ch->peer = NULL;
		module_put(ich->is->owner);
		ret = 0;
		break;
	case CONTROL_CHANNEL:
		ret = channel_bctrl(bch, arg);
		break;
	default:
		pr_info("%s: %s unknown prim(%x)\n",
			ich->is->name, __func__, cmd);
	}
	return ret;
}
Ejemplo n.º 2
0
int
mISDN_freebchannel(struct bchannel *ch)
{
	mISDN_clear_bchannel(ch);
	skb_queue_purge(&ch->rqueue);
	ch->rcount = 0;
	flush_work_sync(&ch->workq);
	return 0;
}
Ejemplo n.º 3
0
static int
w6692_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
{
	struct bchannel *bch = container_of(ch, struct bchannel, ch);
	struct w6692_ch	*bc = container_of(bch, struct w6692_ch, bch);
	struct w6692_hw *card = bch->hw;
	int ret = -EINVAL;
	struct mISDNhead *hh = mISDN_HEAD_P(skb);
	u32 id;
	u_long flags;

	switch (hh->prim) {
	case PH_DATA_REQ:
		spin_lock_irqsave(&card->lock, flags);
		ret = bchannel_senddata(bch, skb);
		if (ret > 0) { 
			id = hh->id; 
			ret = 0;
			W6692_fill_Bfifo(bc);
			spin_unlock_irqrestore(&card->lock, flags);
			if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
				queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
		} else
			spin_unlock_irqrestore(&card->lock, flags);
		return ret;
	case PH_ACTIVATE_REQ:
		spin_lock_irqsave(&card->lock, flags);
		if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags))
			ret = w6692_mode(bc, ch->protocol);
		else
			ret = 0;
		spin_unlock_irqrestore(&card->lock, flags);
		if (!ret)
			_queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
				NULL, GFP_KERNEL);
		break;
	case PH_DEACTIVATE_REQ:
		spin_lock_irqsave(&card->lock, flags);
		mISDN_clear_bchannel(bch);
		w6692_mode(bc, ISDN_P_NONE);
		spin_unlock_irqrestore(&card->lock, flags);
		_queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
			NULL, GFP_KERNEL);
		ret = 0;
		break;
	default:
		pr_info("%s: %s unknown prim(%x,%x)\n",
			card->name, __func__, hh->prim, hh->id);
		ret = -EINVAL;
	}
	if (!ret)
		dev_kfree_skb(skb);
	return ret;
}
Ejemplo n.º 4
0
static int
w6692_mode(struct w6692_ch *wch, u32 pr)
{
	struct w6692_hw	*card;

	card = wch->bch.hw;
	pr_debug("%s: B%d protocol %x-->%x\n", card->name,
		wch->bch.nr, wch->bch.state, pr);
	switch (pr) {
	case ISDN_P_NONE:
		if ((card->fmask & pots) && (wch->b_mode & W_B_MODE_EPCM))
			disable_pots(wch);
		wch->b_mode = 0;
		mISDN_clear_bchannel(&wch->bch);
		WriteW6692B(wch, W_B_MODE, wch->b_mode);
		WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
		test_and_clear_bit(FLG_HDLC, &wch->bch.Flags);
		test_and_clear_bit(FLG_TRANSPARENT, &wch->bch.Flags);
		break;
	case ISDN_P_B_RAW:
		wch->b_mode = W_B_MODE_MMS;
		WriteW6692B(wch, W_B_MODE, wch->b_mode);
		WriteW6692B(wch, W_B_EXIM, 0);
		WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT |
			W_B_CMDR_XRST);
		test_and_set_bit(FLG_TRANSPARENT, &wch->bch.Flags);
		break;
	case ISDN_P_B_HDLC:
		wch->b_mode = W_B_MODE_ITF;
		WriteW6692B(wch, W_B_MODE, wch->b_mode);
		WriteW6692B(wch, W_B_ADM1, 0xff);
		WriteW6692B(wch, W_B_ADM2, 0xff);
		WriteW6692B(wch, W_B_EXIM, 0);
		WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT |
			W_B_CMDR_XRST);
		test_and_set_bit(FLG_HDLC, &wch->bch.Flags);
		break;
	default:
		pr_info("%s: protocol %x not known\n", card->name, pr);
		return -ENOPROTOOPT;
	}
	wch->bch.state = pr;
	return 0;
}
Ejemplo n.º 5
0
static int
isar_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
{
	struct bchannel *bch = container_of(ch, struct bchannel, ch);
	struct isar_ch *ich = container_of(bch, struct isar_ch, bch);
	int ret = -EINVAL;
	struct mISDNhead *hh = mISDN_HEAD_P(skb);
	u32 id, *val;
	u_long flags;

	switch (hh->prim) {
	case PH_DATA_REQ:
		spin_lock_irqsave(ich->is->hwlock, flags);
		ret = bchannel_senddata(bch, skb);
		if (ret > 0) { /* direct TX */
			id = hh->id; /* skb can be freed */
			ret = 0;
			isar_fill_fifo(ich);
			spin_unlock_irqrestore(ich->is->hwlock, flags);
			if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
				queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
		} else
			spin_unlock_irqrestore(ich->is->hwlock, flags);
		return ret;
	case PH_ACTIVATE_REQ:
		spin_lock_irqsave(ich->is->hwlock, flags);
		if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags))
			ret = modeisar(ich, ch->protocol);
		else
			ret = 0;
		spin_unlock_irqrestore(ich->is->hwlock, flags);
		if (!ret)
			_queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
				NULL, GFP_KERNEL);
		break;
	case PH_DEACTIVATE_REQ:
		spin_lock_irqsave(ich->is->hwlock, flags);
		mISDN_clear_bchannel(bch);
		modeisar(ich, ISDN_P_NONE);
		spin_unlock_irqrestore(ich->is->hwlock, flags);
		_queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
			NULL, GFP_KERNEL);
		ret = 0;
		break;
	case PH_CONTROL_REQ:
		val = (u32 *)skb->data;
		pr_debug("%s: PH_CONTROL | REQUEST %x/%x\n", ich->is->name,
			hh->id, *val);
		if ((hh->id == 0) && ((*val & ~DTMF_TONE_MASK) ==
		    DTMF_TONE_VAL)) {
			if (bch->state == ISDN_P_B_L2DTMF) {
				char tt = *val & DTMF_TONE_MASK;

				if (tt == '*')
					tt = 0x1e;
				else if (tt == '#')
					tt = 0x1f;
				else if (tt > '9')
					tt -= 7;
				tt &= 0x1f;
				spin_lock_irqsave(ich->is->hwlock, flags);
				isar_pump_cmd(ich, PCTRL_CMD_TDTMF, tt);
				spin_unlock_irqrestore(ich->is->hwlock, flags);
			} else {
				pr_info("%s: DTMF send wrong protocol %x\n",
					__func__, bch->state);
				return -EINVAL;
			}
		} else if ((hh->id == HW_MOD_FRM) || (hh->id == HW_MOD_FRH) ||
		    (hh->id == HW_MOD_FTM) || (hh->id == HW_MOD_FTH)) {
			for (id = 0; id < FAXMODCNT; id++)
				if (faxmodulation[id] == *val)
					break;
			if ((FAXMODCNT > id) &&
			    test_bit(FLG_INITIALIZED, &bch->Flags)) {
				pr_debug("%s: isar: new mod\n", ich->is->name);
				isar_pump_cmd(ich, hh->id, *val);
				ret = 0;
			} else {
				pr_info("%s: wrong modulation\n",
					ich->is->name);
				ret = -EINVAL;
			}
		} else if (hh->id == HW_MOD_LASTDATA)
			test_and_set_bit(FLG_DLEETX, &bch->Flags);
		else {
			pr_info("%s: unknown PH_CONTROL_REQ %x\n",
				ich->is->name, hh->id);
			ret = -EINVAL;
		}
	default:
		pr_info("%s: %s unknown prim(%x,%x)\n",
			ich->is->name, __func__, hh->prim, hh->id);
		ret = -EINVAL;
	}
	if (!ret)
		dev_kfree_skb(skb);
	return ret;
}
Ejemplo n.º 6
0
void
mISDN_freebchannel(struct bchannel *ch)
{
	cancel_work_sync(&ch->workq);
	mISDN_clear_bchannel(ch);
}