Ejemplo n.º 1
0
/*
 * st5481_b_l2l1 is the entry point for upper layer routines that want to
 * transmit on the B channel.  PH_DATA | REQUEST is a normal packet that
 * we either start transmitting (if idle) or queue (if busy).
 * PH_PULL | REQUEST can be called to request a callback message
 * (PH_PULL | CONFIRM)
 * once the link is idle.  After a "pull" callback, the upper layer
 * routines can use PH_PULL | INDICATION to send data.
 */
void st5481_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
{
	struct st5481_bcs *bcs = ifc->priv;
	struct sk_buff *skb = arg;
	int mode;

	DBG(4, "");

	switch (pr) {
	case PH_DATA | REQUEST:
		if (bcs->b_out.tx_skb)
			BUG();
		
		bcs->b_out.tx_skb = skb;
		break;
	case PH_ACTIVATE | REQUEST:
		mode = (int) arg;
		DBG(4,"B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode);
		st5481B_mode(bcs, mode);
		B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL);
		break;
	case PH_DEACTIVATE | REQUEST:
		DBG(4,"B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1);
		st5481B_mode(bcs, L1_MODE_NULL);
		B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL);
		break;
	default:
		WARN("pr %#x\n", pr);
	}
}
Ejemplo n.º 2
0
static void fritz_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
{
	struct fritz_bcs *bcs = ifc->priv;
	struct sk_buff *skb = arg;
	int mode;

	DBG(0x10, "pr %#x", pr);

	switch (pr) {
	case PH_DATA | REQUEST:
		if (bcs->tx_skb)
			BUG();
		
		bcs->tx_skb = skb;
		DBG_SKB(1, skb);
		hdlc_fill_fifo(bcs);
		break;
	case PH_ACTIVATE | REQUEST:
		mode = (int) arg;
		DBG(4,"B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode);
		modehdlc(bcs, mode);
		B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL);
		break;
	case PH_DEACTIVATE | REQUEST:
		DBG(4,"B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1);
		modehdlc(bcs, L1_MODE_NULL);
		B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL);
		break;
	}
}
Ejemplo n.º 3
0
static inline void hdlc_xpr_irq(struct fritz_bcs *bcs)
{
	struct sk_buff *skb;

	skb = bcs->tx_skb;
	if (!skb)
		return;

	if (skb->len) {
		hdlc_fill_fifo(bcs);
		return;
	}
	bcs->tx_cnt = 0;
	bcs->tx_skb = NULL;
	B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
	dev_kfree_skb_irq(skb);
}
Ejemplo n.º 4
0
static inline void hdlc_rpr_irq(struct fritz_bcs *bcs, u32 stat)
{
	struct fritz_adapter *adapter = bcs->adapter;
	struct sk_buff *skb;
	int len;

	if (stat & HDLC_STAT_RDO) {
		DBG(0x10, "RDO");
		bcs->ctrl.sr.xml = 0;
		bcs->ctrl.sr.cmd |= HDLC_CMD_RRS;
		adapter->write_ctrl(bcs, 1);
		bcs->ctrl.sr.cmd &= ~HDLC_CMD_RRS;
		adapter->write_ctrl(bcs, 1);
		bcs->rcvidx = 0;
		return;
	}

	len = (stat & HDLC_STAT_RML_MASK) >> 8;
	if (len == 0)
		len = 32;

	hdlc_empty_fifo(bcs, len);

	if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {
		if (((stat & HDLC_STAT_CRCVFRRAB)== HDLC_STAT_CRCVFR) ||
		    (bcs->mode == L1_MODE_TRANS)) {
			skb = dev_alloc_skb(bcs->rcvidx);
			if (!skb) {
				printk(KERN_WARNING "HDLC: receive out of memory\n");
			} else {
				memcpy(skb_put(skb, bcs->rcvidx), bcs->rcvbuf,
				       bcs->rcvidx);
				DBG_SKB(1, skb);
				B_L1L2(bcs, PH_DATA | INDICATION, skb);
			}
			bcs->rcvidx = 0;
		} else {
			DBG(0x10, "ch%d invalid frame %#x",
			    bcs->channel, stat);
			bcs->rcvidx = 0;
		}
	}
}
Ejemplo n.º 5
0
/*
 * Encode and transmit next frame.
 */
static void usb_b_out(struct st5481_bcs *bcs,int buf_nr)
{
	struct st5481_b_out *b_out = &bcs->b_out;
	struct st5481_adapter *adapter = bcs->adapter;
	struct urb *urb;
	unsigned int packet_size,offset;
	int len,buf_size,bytes_sent;
	int i;
	struct sk_buff *skb;
	
	if (test_and_set_bit(buf_nr, &b_out->busy)) {
		DBG(4,"ep %d urb %d busy",(bcs->channel+1)*2,buf_nr);
		return;
	}
	urb = b_out->urb[buf_nr];

	// Adjust isoc buffer size according to flow state
	if(b_out->flow_event & (OUT_DOWN | OUT_UNDERRUN)) {
		buf_size = NUM_ISO_PACKETS_B*SIZE_ISO_PACKETS_B_OUT + B_FLOW_ADJUST;
		packet_size = SIZE_ISO_PACKETS_B_OUT + B_FLOW_ADJUST;
		DBG(4,"B%d,adjust flow,add %d bytes",bcs->channel+1,B_FLOW_ADJUST);
	} else if(b_out->flow_event & OUT_UP){
		buf_size = NUM_ISO_PACKETS_B*SIZE_ISO_PACKETS_B_OUT - B_FLOW_ADJUST;
		packet_size = SIZE_ISO_PACKETS_B_OUT - B_FLOW_ADJUST;
		DBG(4,"B%d,adjust flow,remove %d bytes",bcs->channel+1,B_FLOW_ADJUST);
	} else {
		buf_size = NUM_ISO_PACKETS_B*SIZE_ISO_PACKETS_B_OUT;
		packet_size = 8;
	}
	b_out->flow_event = 0;

	len = 0;
	while (len < buf_size) {
		if ((skb = b_out->tx_skb)) {
			DBG_SKB(0x100, skb);
			DBG(4,"B%d,len=%d",bcs->channel+1,skb->len);
			
			if (bcs->mode == L1_MODE_TRANS) {	
				bytes_sent = buf_size - len;
				if (skb->len < bytes_sent)
					bytes_sent = skb->len;
				{	/* swap tx bytes to get hearable audio data */
					register unsigned char *src  = skb->data;
					register unsigned char *dest = urb->transfer_buffer+len;
					register unsigned int count;
					for (count = 0; count < bytes_sent; count++)
						*dest++ = isdnhdlc_bit_rev_tab[*src++];
				}
				len += bytes_sent;
			} else {
				len += isdnhdlc_encode(&b_out->hdlc_state,
						       skb->data, skb->len, &bytes_sent,
						       urb->transfer_buffer+len, buf_size-len);
			}

			skb_pull(skb, bytes_sent);

			if (!skb->len) {
				// Frame sent
				b_out->tx_skb = NULL;
				B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
				dev_kfree_skb_any(skb);

/* 				if (!(bcs->tx_skb = skb_dequeue(&bcs->sq))) { */
/* 					st5481B_sched_event(bcs, B_XMTBUFREADY); */
/* 				} */
			}
		} else {
			if (bcs->mode == L1_MODE_TRANS) {
				memset(urb->transfer_buffer+len, 0xff, buf_size-len);
				len = buf_size;
			} else {
				// Send flags
				len += isdnhdlc_encode(&b_out->hdlc_state,
						       NULL, 0, &bytes_sent,
						       urb->transfer_buffer+len, buf_size-len);
			}
		}	
	}

	// Prepare the URB
	for (i = 0, offset = 0; offset < len; i++) {
		urb->iso_frame_desc[i].offset = offset;
		urb->iso_frame_desc[i].length = packet_size;
		offset += packet_size;
		packet_size = SIZE_ISO_PACKETS_B_OUT;
	}
	urb->transfer_buffer_length = len;
	urb->number_of_packets = i;
	urb->dev = adapter->usb_dev;

	DBG_ISO_PACKET(0x200,urb);

	SUBMIT_URB(urb, GFP_NOIO);
}