static void check_send(struct isar_hw *isar, u8 rdm) { struct isar_ch *ch; pr_debug("%s: rdm %x\n", isar->name, rdm); if (rdm & BSTAT_RDM1) { ch = sel_bch_isar(isar, 1); if (ch && test_bit(FLG_ACTIVE, &ch->bch.Flags)) { if (ch->bch.tx_skb && (ch->bch.tx_skb->len > ch->bch.tx_idx)) isar_fill_fifo(ch); else send_next(ch); } } if (rdm & BSTAT_RDM2) { ch = sel_bch_isar(isar, 2); if (ch && test_bit(FLG_ACTIVE, &ch->bch.Flags)) { if (ch->bch.tx_skb && (ch->bch.tx_skb->len > ch->bch.tx_idx)) isar_fill_fifo(ch); else send_next(ch); } } }
static void send_next(struct isar_ch *ch) { pr_debug("%s: %s ch%d tx_skb %d tx_idx %d\n", ch->is->name, __func__, ch->bch.nr, ch->bch.tx_skb ? ch->bch.tx_skb->len : -1, ch->bch.tx_idx); if (ch->bch.state == ISDN_P_B_T30_FAX) { if (ch->cmd == PCTRL_CMD_FTH) { if (test_bit(FLG_LASTDATA, &ch->bch.Flags)) { pr_debug("set NMD_DATA\n"); test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags); } } else if (ch->cmd == PCTRL_CMD_FTM) { if (test_bit(FLG_DLEETX, &ch->bch.Flags)) { test_and_set_bit(FLG_LASTDATA, &ch->bch.Flags); test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags); } } } if (ch->bch.tx_skb) dev_kfree_skb(ch->bch.tx_skb); if (get_next_bframe(&ch->bch)) { isar_fill_fifo(ch); test_and_clear_bit(FLG_TX_EMPTY, &ch->bch.Flags); } else if (test_bit(FLG_TX_EMPTY, &ch->bch.Flags)) { isar_fill_fifo(ch); } else { if (test_and_clear_bit(FLG_DLEETX, &ch->bch.Flags)) { if (test_and_clear_bit(FLG_LASTDATA, &ch->bch.Flags)) { if (test_and_clear_bit(FLG_NMD_DATA, &ch->bch.Flags)) { u8 zd = 0; send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, 0x01, 1, &zd); } test_and_set_bit(FLG_LL_OK, &ch->bch.Flags); } else { deliver_status(ch, HW_MOD_CONNECT); } } else if (test_bit(FLG_FILLEMPTY, &ch->bch.Flags)) { test_and_set_bit(FLG_TX_EMPTY, &ch->bch.Flags); } } }
static void send_next(struct isar_ch *ch) { pr_debug("%s: %s ch%d tx_skb %p tx_idx %d\n", ch->is->name, __func__, ch->bch.nr, ch->bch.tx_skb, ch->bch.tx_idx); if (ch->bch.state == ISDN_P_B_T30_FAX) { if (ch->cmd == PCTRL_CMD_FTH) { if (test_bit(FLG_LASTDATA, &ch->bch.Flags)) { pr_debug("set NMD_DATA\n"); test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags); } } else if (ch->cmd == PCTRL_CMD_FTM) { if (test_bit(FLG_DLEETX, &ch->bch.Flags)) { test_and_set_bit(FLG_LASTDATA, &ch->bch.Flags); test_and_set_bit(FLG_NMD_DATA, &ch->bch.Flags); } } } if (ch->bch.tx_skb) { /* send confirm, on trans, free on hdlc. */ if (test_bit(FLG_TRANSPARENT, &ch->bch.Flags)) confirm_Bsend(&ch->bch); dev_kfree_skb(ch->bch.tx_skb); } if (get_next_bframe(&ch->bch)) isar_fill_fifo(ch); else { if (test_and_clear_bit(FLG_DLEETX, &ch->bch.Flags)) { if (test_and_clear_bit(FLG_LASTDATA, &ch->bch.Flags)) { if (test_and_clear_bit(FLG_NMD_DATA, &ch->bch.Flags)) { u8 zd = 0; send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, 0x01, 1, &zd); } test_and_set_bit(FLG_LL_OK, &ch->bch.Flags); } else { deliver_status(ch, HW_MOD_CONNECT); } } } }
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; }