Esempio n. 1
0
static void
W6692_empty_Dfifo(struct w6692_hw *card, int count)
{
	struct dchannel *dch = &card->dch;
	u8 *ptr;

	pr_debug("%s: empty_Dfifo %d\n", card->name, count);
	if (!dch->rx_skb) {
		dch->rx_skb = mI_alloc_skb(card->dch.maxlen, GFP_ATOMIC);
		if (!dch->rx_skb) {
			pr_info("%s: D receive out of memory\n", card->name);
			WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);
			return;
		}
	}
	if ((dch->rx_skb->len + count) >= dch->maxlen) {
		pr_debug("%s: empty_Dfifo overrun %d\n", card->name,
			dch->rx_skb->len + count);
		WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);
		return;
	}
	ptr = skb_put(dch->rx_skb, count);
	insb(card->addr + W_D_RFIFO, ptr, count);
	WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);
	if (debug & DEBUG_HW_DFIFO) {
		snprintf(card->log, 63, "D-recv %s %d ",
			card->name, count);
		print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count);
	}
}
Esempio n. 2
0
void
isac_empty_fifo(struct isac_hw *isac, int count)
{
	u8 *ptr;

	pr_debug("%s: %s  %d\n", isac->name, __func__, count);

	if (!isac->dch.rx_skb) {
		isac->dch.rx_skb = mI_alloc_skb(isac->dch.maxlen, GFP_ATOMIC);
		if (!isac->dch.rx_skb) {
			pr_info("%s: D receive out of memory\n", isac->name);
			WriteISAC(isac, ISAC_CMDR, 0x80);
			return;
		}
	}
	if ((isac->dch.rx_skb->len + count) >= isac->dch.maxlen) {
		pr_debug("%s: %s overrun %d\n", isac->name, __func__,
			    isac->dch.rx_skb->len + count);
		WriteISAC(isac, ISAC_CMDR, 0x80);
		return;
	}
	ptr = skb_put(isac->dch.rx_skb, count);
	isac->read_fifo(isac->dch.hw, isac->off, ptr, count);
	WriteISAC(isac, ISAC_CMDR, 0x80);
	if (isac->dch.debug & DEBUG_HW_DFIFO) {
		char	pfx[MISDN_MAX_IDLEN + 16];

		snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-recv %s %d ",
			isac->name, count);
		print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count);
	}
}
Esempio n. 3
0
/* The function allocates a new receive skb on demand with a size for the
 * requirements of the current protocol. It returns the tailroom of the
 * receive skb or an error.
 */
int
bchannel_get_rxbuf(struct bchannel *bch, int reqlen)
{
	int len;

	if (bch->rx_skb) {
		len = skb_tailroom(bch->rx_skb);
		if (len < reqlen) {
			pr_warning("B%d no space for %d (only %d) bytes\n",
				   bch->nr, reqlen, len);
			if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
				/* send what we have now and try a new buffer */
				recv_Bchannel(bch, 0, true);
			} else {
				/* on HDLC we have to drop too big frames */
				return -EMSGSIZE;
			}
		} else {
			return len;
		}
	}
	/* update current min/max length first */
	if (unlikely(bch->maxlen != bch->next_maxlen))
		bch->maxlen = bch->next_maxlen;
	if (unlikely(bch->minlen != bch->next_minlen))
		bch->minlen = bch->next_minlen;
	if (unlikely(reqlen > bch->maxlen))
		return -EMSGSIZE;
	if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
		if (reqlen >= bch->minlen) {
			len = reqlen;
		} else {
			len = 2 * bch->minlen;
			if (len > bch->maxlen)
				len = bch->maxlen;
		}
	} else {
		/* with HDLC we do not know the length yet */
		len = bch->maxlen;
	}
	bch->rx_skb = mI_alloc_skb(len, GFP_ATOMIC);
	if (!bch->rx_skb) {
		pr_warning("B%d receive no memory for %d bytes\n",
			   bch->nr, len);
		len = -ENOMEM;
	}
	return len;
}
Esempio n. 4
0
static int
l2down_create(struct layer2 *l2, u_int prim, u_int id, int len, void *arg)
{
	struct sk_buff	*skb;
	int		err;
	struct mISDNhead *hh;

	skb = mI_alloc_skb(len, GFP_ATOMIC);
	if (!skb)
		return -ENOMEM;
	hh = mISDN_HEAD_P(skb);
	hh->prim = prim;
	hh->id = id;
	if (len)
		memcpy(skb_put(skb, len), arg, len);
	err = l2down_raw(l2, skb);
	if (err)
		dev_kfree_skb(skb);
	return err;
}
Esempio n. 5
0
static void
send_uframe(struct layer2 *l2, struct sk_buff *skb, u_char cmd, u_char cr)
{
	u_char tmp[MAX_L2HEADER_LEN];
	int i;

	i = sethdraddr(l2, tmp, cr);
	tmp[i++] = cmd;
	if (skb)
		skb_trim(skb, 0);
	else {
		skb = mI_alloc_skb(i, GFP_ATOMIC);
		if (!skb) {
			printk(KERN_WARNING "%s: can't alloc skbuff\n",
				__func__);
			return;
		}
	}
	memcpy(skb_put(skb, i), tmp, i);
	enqueue_super(l2, skb);
}
Esempio n. 6
0
static void
enquiry_cr(struct layer2 *l2, u_char typ, u_char cr, u_char pf)
{
	struct sk_buff *skb;
	u_char tmp[MAX_L2HEADER_LEN];
	int i;

	i = sethdraddr(l2, tmp, cr);
	if (test_bit(FLG_MOD128, &l2->flag)) {
		tmp[i++] = typ;
		tmp[i++] = (l2->vr << 1) | (pf ? 1 : 0);
	} else
		tmp[i++] = (l2->vr << 5) | typ | (pf ? 0x10 : 0);
	skb = mI_alloc_skb(i, GFP_ATOMIC);
	if (!skb) {
		printk(KERN_WARNING
		    "isdnl2 can't alloc sbbuff for enquiry_cr\n");
		return;
	}
	memcpy(skb_put(skb, i), tmp, i);
	enqueue_super(l2, skb);
}
Esempio n. 7
0
static void
W6692_empty_Bfifo(struct w6692_ch *wch, int count)
{
	struct w6692_hw *card = wch->bch.hw;
	u8 *ptr;

	pr_debug("%s: empty_Bfifo %d\n", card->name, count);
	if (unlikely(wch->bch.state == ISDN_P_NONE)) {
		pr_debug("%s: empty_Bfifo ISDN_P_NONE\n", card->name);
		WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
		if (wch->bch.rx_skb)
			skb_trim(wch->bch.rx_skb, 0);
		return;
	}
	if (!wch->bch.rx_skb) {
		wch->bch.rx_skb = mI_alloc_skb(wch->bch.maxlen, GFP_ATOMIC);
		if (unlikely(!wch->bch.rx_skb)) {
			pr_info("%s: B receive out of memory\n", card->name);
			WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK |
				W_B_CMDR_RACT);
			return;
		}
	}
	if (wch->bch.rx_skb->len + count > wch->bch.maxlen) {
		pr_debug("%s: empty_Bfifo incoming packet too large\n",
			card->name);
		WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
		skb_trim(wch->bch.rx_skb, 0);
		return;
	}
	ptr = skb_put(wch->bch.rx_skb, count);
	insb(wch->addr + W_B_RFIFO, ptr, count);
	WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
	if (debug & DEBUG_HW_DFIFO) {
		snprintf(card->log, 63, "B%1d-recv %s %d ",
			wch->bch.nr, card->name, count);
		print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count);
	}
}
Esempio n. 8
0
static void
l2up_create(struct layer2 *l2, u_int prim, int len, void *arg)
{
	struct sk_buff	*skb;
	struct mISDNhead *hh;
	int		err;

	if (!l2->up)
		return;
	skb = mI_alloc_skb(len, GFP_ATOMIC);
	if (!skb)
		return;
	hh = mISDN_HEAD_P(skb);
	hh->prim = prim;
	hh->id = (l2->ch.nr << 16) | l2->ch.addr;
	if (len)
		memcpy(skb_put(skb, len), arg, len);
	err = l2->up->send(l2->up, skb);
	if (err) {
		printk(KERN_WARNING "%s: err=%d\n", __func__, err);
		dev_kfree_skb(skb);
	}
}
static void
hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
		 int finish)
{
	struct hfcsusb	*hw = fifo->hw;
	struct sk_buff	*rx_skb = NULL;
	int		maxlen = 0;
	int		fifon = fifo->fifonum;
	int		i;
	int		hdlc = 0;

	if (debug & DBG_HFC_CALL_TRACE)
		printk(KERN_DEBUG "%s: %s: fifo(%i) len(%i) "
		       "dch(%p) bch(%p) ech(%p)\n",
		       hw->name, __func__, fifon, len,
		       fifo->dch, fifo->bch, fifo->ech);

	if (!len)
		return;

	if ((!!fifo->dch + !!fifo->bch + !!fifo->ech) != 1) {
		printk(KERN_DEBUG "%s: %s: undefined channel\n",
		       hw->name, __func__);
		return;
	}

	spin_lock(&hw->lock);
	if (fifo->dch) {
		rx_skb = fifo->dch->rx_skb;
		maxlen = fifo->dch->maxlen;
		hdlc = 1;
	}
	if (fifo->bch) {
		rx_skb = fifo->bch->rx_skb;
		maxlen = fifo->bch->maxlen;
		hdlc = test_bit(FLG_HDLC, &fifo->bch->Flags);
	}
	if (fifo->ech) {
		rx_skb = fifo->ech->rx_skb;
		maxlen = fifo->ech->maxlen;
		hdlc = 1;
	}

	if (!rx_skb) {
		rx_skb = mI_alloc_skb(maxlen, GFP_ATOMIC);
		if (rx_skb) {
			if (fifo->dch)
				fifo->dch->rx_skb = rx_skb;
			if (fifo->bch)
				fifo->bch->rx_skb = rx_skb;
			if (fifo->ech)
				fifo->ech->rx_skb = rx_skb;
			skb_trim(rx_skb, 0);
		} else {
			printk(KERN_DEBUG "%s: %s: No mem for rx_skb\n",
			       hw->name, __func__);
			spin_unlock(&hw->lock);
			return;
		}
	}

	if (fifo->dch || fifo->ech) {
		
		if ((rx_skb->len + len) >= MAX_DFRAME_LEN_L1) {
			printk(KERN_DEBUG "%s: %s: sbk mem exceeded "
			       "for fifo(%d) HFCUSB_D_RX\n",
			       hw->name, __func__, fifon);
			skb_trim(rx_skb, 0);
			spin_unlock(&hw->lock);
			return;
		}
	} else if (fifo->bch) {
		
		if ((rx_skb->len + len) >= (MAX_BCH_SIZE + 3)) {
			printk(KERN_DEBUG "%s: %s: sbk mem exceeded "
			       "for fifo(%d) HFCUSB_B_RX\n",
			       hw->name, __func__, fifon);
			skb_trim(rx_skb, 0);
			spin_unlock(&hw->lock);
			return;
		}
	}

	memcpy(skb_put(rx_skb, len), data, len);

	if (hdlc) {
		
		if (finish) {
			if ((rx_skb->len > 3) &&
			    (!(rx_skb->data[rx_skb->len - 1]))) {
				if (debug & DBG_HFC_FIFO_VERBOSE) {
					printk(KERN_DEBUG "%s: %s: fifon(%i)"
					       " new RX len(%i): ",
					       hw->name, __func__, fifon,
					       rx_skb->len);
					i = 0;
					while (i < rx_skb->len)
						printk("%02x ",
						       rx_skb->data[i++]);
					printk("\n");
				}

				
				skb_trim(rx_skb, rx_skb->len - 3);

				if (fifo->dch)
					recv_Dchannel(fifo->dch);
				if (fifo->bch)
					recv_Bchannel(fifo->bch, MISDN_ID_ANY);
				if (fifo->ech)
					recv_Echannel(fifo->ech,
						      &hw->dch);
			} else {
				if (debug & DBG_HFC_FIFO_VERBOSE) {
					printk(KERN_DEBUG
					       "%s: CRC or minlen ERROR fifon(%i) "
					       "RX len(%i): ",
					       hw->name, fifon, rx_skb->len);
					i = 0;
					while (i < rx_skb->len)
						printk("%02x ",
						       rx_skb->data[i++]);
					printk("\n");
				}
				skb_trim(rx_skb, 0);
			}
		}
	} else {
		
		if (rx_skb->len >= poll)
			recv_Bchannel(fifo->bch, MISDN_ID_ANY);
	}
	spin_unlock(&hw->lock);
}
Esempio n. 10
0
static inline void
isar_rcv_frame(struct isar_ch *ch)
{
	u8		*ptr;

	if (!ch->is->clsb) {
		pr_debug("%s; ISAR zero len frame\n", ch->is->name);
		ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
		return;
	}
	switch (ch->bch.state) {
	case ISDN_P_NONE:
		pr_debug("%s: ISAR protocol 0 spurious IIS_RDATA %x/%x/%x\n",
			ch->is->name, ch->is->iis, ch->is->cmsb, ch->is->clsb);
		ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
		break;
	case ISDN_P_B_RAW:
	case ISDN_P_B_L2DTMF:
	case ISDN_P_B_MODEM_ASYNC:
		if (!ch->bch.rx_skb) {
			ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen,
						GFP_ATOMIC);
			if (unlikely(!ch->bch.rx_skb)) {
				pr_info("%s: B receive out of memory\n",
					ch->is->name);
				ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
				break;
			}
		}
		rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb));
		recv_Bchannel(&ch->bch, 0);
		break;
	case ISDN_P_B_HDLC:
		if (!ch->bch.rx_skb) {
			ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen,
						GFP_ATOMIC);
			if (unlikely(!ch->bch.rx_skb)) {
				pr_info("%s: B receive out of memory\n",
					ch->is->name);
				ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
				break;
			}
		}
		if ((ch->bch.rx_skb->len + ch->is->clsb) >
		    (ch->bch.maxlen + 2)) {
			pr_debug("%s: incoming packet too large\n",
				ch->is->name);
			ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
			skb_trim(ch->bch.rx_skb, 0);
			break;
		}
		if (ch->is->cmsb & HDLC_ERROR) {
			pr_debug("%s: ISAR frame error %x len %d\n",
				ch->is->name, ch->is->cmsb, ch->is->clsb);
#ifdef ERROR_STATISTIC
			if (ch->is->cmsb & HDLC_ERR_RER)
				ch->bch.err_inv++;
			if (ch->is->cmsb & HDLC_ERR_CER)
				ch->bch.err_crc++;
#endif
			skb_trim(ch->bch.rx_skb, 0);
			ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
			break;
		}
		if (ch->is->cmsb & HDLC_FSD)
			skb_trim(ch->bch.rx_skb, 0);
		ptr = skb_put(ch->bch.rx_skb, ch->is->clsb);
		rcv_mbox(ch->is, ptr);
		if (ch->is->cmsb & HDLC_FED) {
			if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */
				pr_debug("%s: ISAR frame to short %d\n",
					ch->is->name, ch->bch.rx_skb->len);
				skb_trim(ch->bch.rx_skb, 0);
				break;
			}
			skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2);
			recv_Bchannel(&ch->bch, 0);
		}
		break;
	case ISDN_P_B_T30_FAX:
		if (ch->state != STFAX_ACTIV) {
			pr_debug("%s: isar_rcv_frame: not ACTIV\n",
				ch->is->name);
			ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
			if (ch->bch.rx_skb)
				skb_trim(ch->bch.rx_skb, 0);
			break;
		}
		if (!ch->bch.rx_skb) {
			ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen,
						GFP_ATOMIC);
			if (unlikely(!ch->bch.rx_skb)) {
				pr_info("%s: B receive out of memory\n",
					__func__);
				ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
				break;
			}
		}
		if (ch->cmd == PCTRL_CMD_FRM) {
			rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb));
			pr_debug("%s: isar_rcv_frame: %d\n",
				ch->is->name, ch->bch.rx_skb->len);
			if (ch->is->cmsb & SART_NMD) { /* ABORT */
				pr_debug("%s: isar_rcv_frame: no more data\n",
					ch->is->name);
				ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
				send_mbox(ch->is, SET_DPS(ch->dpath) |
					ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC,
					0, NULL);
				ch->state = STFAX_ESCAPE;
				/* set_skb_flag(skb, DF_NOMOREDATA); */
			}
			recv_Bchannel(&ch->bch, 0);
			if (ch->is->cmsb & SART_NMD)
				deliver_status(ch, HW_MOD_NOCARR);
			break;
		}
		if (ch->cmd != PCTRL_CMD_FRH) {
			pr_debug("%s: isar_rcv_frame: unknown fax mode %x\n",
				ch->is->name, ch->cmd);
			ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
			if (ch->bch.rx_skb)
				skb_trim(ch->bch.rx_skb, 0);
			break;
		}
		/* PCTRL_CMD_FRH */
		if ((ch->bch.rx_skb->len + ch->is->clsb) >
		    (ch->bch.maxlen + 2)) {
			pr_info("%s: %s incoming packet too large\n",
				ch->is->name, __func__);
			ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
			skb_trim(ch->bch.rx_skb, 0);
			break;
		}  else if (ch->is->cmsb & HDLC_ERROR) {
			pr_info("%s: ISAR frame error %x len %d\n",
				ch->is->name, ch->is->cmsb, ch->is->clsb);
			skb_trim(ch->bch.rx_skb, 0);
			ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
			break;
		}
		if (ch->is->cmsb & HDLC_FSD)
			skb_trim(ch->bch.rx_skb, 0);
		ptr = skb_put(ch->bch.rx_skb, ch->is->clsb);
		rcv_mbox(ch->is, ptr);
		if (ch->is->cmsb & HDLC_FED) {
			if (ch->bch.rx_skb->len < 3) { /* last 2 are the FCS */
				pr_info("%s: ISAR frame to short %d\n",
					ch->is->name, ch->bch.rx_skb->len);
				skb_trim(ch->bch.rx_skb, 0);
				break;
			}
			skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2);
			recv_Bchannel(&ch->bch, 0);
		}
		if (ch->is->cmsb & SART_NMD) { /* ABORT */
			pr_debug("%s: isar_rcv_frame: no more data\n",
				ch->is->name);
			ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
			if (ch->bch.rx_skb)
				skb_trim(ch->bch.rx_skb, 0);
			send_mbox(ch->is, SET_DPS(ch->dpath) |
				ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL);
			ch->state = STFAX_ESCAPE;
			deliver_status(ch, HW_MOD_NOCARR);
		}
		break;
	default:
		pr_info("isar_rcv_frame protocol (%x)error\n", ch->bch.state);
		ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
		break;
	}
}