Beispiel #1
0
static void
tx_d_frame(struct hfc4s8s_l1 *l1p)
{
	struct sk_buff *skb;
	u_char f1, f2;
	u_char *cp;
	long cnt;

	if (l1p->l1_state != 7)
		return;

	/* TX fifo */
	Write_hfc8(l1p->hw, R_FIFO, (l1p->st_num * 8 + 4));
	wait_busy(l1p->hw);

	f1 = Read_hfc8(l1p->hw, A_F1);
	f2 = Read_hfc8_stable(l1p->hw, A_F2);

	if ((f1 ^ f2) & MAX_F_CNT)
		return;		/* fifo is still filled */

	if (l1p->tx_cnt > 0) {
		cnt = l1p->tx_cnt;
		l1p->tx_cnt = 0;
		l1p->d_if.ifc.l1l2(&l1p->d_if.ifc, PH_DATA | CONFIRM,
				   (void *) cnt);
	}

	if ((skb = skb_dequeue(&l1p->d_tx_queue))) {
		cp = skb->data;
		cnt = skb->len;
		SetRegAddr(l1p->hw, A_FIFO_DATA0);

		while (cnt >= 4) {
			SetRegAddr(l1p->hw, A_FIFO_DATA0);
			fWrite_hfc32(l1p->hw, *(unsigned long *) cp);
			cp += 4;
			cnt -= 4;
		}

		while (cnt--)
			fWrite_hfc8(l1p->hw, *cp++);

		l1p->tx_cnt = skb->truesize;
		Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1);	/* increment f counter */
		wait_busy(l1p->hw);

		dev_kfree_skb(skb);
	}
}				/* tx_d_frame */
Beispiel #2
0
static void
tx_b_frame(struct hfc4s8s_btype *bch)
{
	struct sk_buff *skb;
	struct hfc4s8s_l1 *l1 = bch->l1p;
	u_char *cp;
	int cnt, max, hdlc_num;
	long ack_len = 0;

	if (!l1->enabled || (bch->mode == L1_MODE_NULL))
		return;

	/* TX fifo */
	Write_hfc8(l1->hw, R_FIFO,
		   (l1->st_num * 8 + ((bch->bchan == 1) ? 0 : 2)));
	wait_busy(l1->hw);
	do {

		if (bch->mode == L1_MODE_HDLC) {
			hdlc_num = Read_hfc8(l1->hw, A_F1) & MAX_F_CNT;
			hdlc_num -=
			    (Read_hfc8_stable(l1->hw, A_F2) & MAX_F_CNT);
			if (hdlc_num < 0)
				hdlc_num += 16;
			if (hdlc_num >= 15)
				break;	/* fifo still filled up with hdlc frames */
		} else
			hdlc_num = 0;

		if (!(skb = bch->tx_skb)) {
			if (!(skb = skb_dequeue(&bch->tx_queue))) {
				l1->hw->mr.fifo_slow_timer_service[l1->
								   st_num]
				    &= ~((bch->bchan == 1) ? 1 : 4);
				break;	/* list empty */
			}
			bch->tx_skb = skb;
			bch->tx_cnt = 0;
		}

		if (!hdlc_num)
			l1->hw->mr.fifo_slow_timer_service[l1->st_num] |=
			    ((bch->bchan == 1) ? 1 : 4);
		else
			l1->hw->mr.fifo_slow_timer_service[l1->st_num] &=
			    ~((bch->bchan == 1) ? 1 : 4);

		max = Read_hfc16_stable(l1->hw, A_Z2);
		max -= Read_hfc16(l1->hw, A_Z1);
		if (max <= 0)
			max += 384;
		max--;

		if (max < 16)
			break;	/* don't write to small amounts of bytes */

		cnt = skb->len - bch->tx_cnt;
		if (cnt > max)
			cnt = max;
		cp = skb->data + bch->tx_cnt;
		bch->tx_cnt += cnt;

#ifndef HISAX_HFC4S8S_PCIMEM
		SetRegAddr(l1->hw, A_FIFO_DATA0);
#endif
		while (cnt >= 4) {
#ifdef HISAX_HFC4S8S_PCIMEM
			fWrite_hfc32(l1->hw, A_FIFO_DATA0,
				     *(unsigned long *) cp);
#else
			fWrite_hfc32(l1->hw, *(unsigned long *) cp);
#endif
			cp += 4;
			cnt -= 4;
		}

		while (cnt--)
#ifdef HISAX_HFC4S8S_PCIMEM
			fWrite_hfc8(l1->hw, A_FIFO_DATA0, *cp++);
#else
			fWrite_hfc8(l1->hw, *cp++);
#endif

		if (bch->tx_cnt >= skb->len) {
			if (bch->mode == L1_MODE_HDLC) {
				/* increment f counter */
				Write_hfc8(l1->hw, A_INC_RES_FIFO, 1);
			}
			ack_len += skb->truesize;
			bch->tx_skb = NULL;
			bch->tx_cnt = 0;
			dev_kfree_skb(skb);
		} else
			/* Re-Select */
			Write_hfc8(l1->hw, R_FIFO,
				   (l1->st_num * 8 +
				    ((bch->bchan == 1) ? 0 : 2)));
		wait_busy(l1->hw);
	} while (1);

	if (ack_len)
		bch->b_if.ifc.l1l2((struct hisax_if *) &bch->b_if,
				   PH_DATA | CONFIRM, (void *) ack_len);
}				/* tx_b_frame */
Beispiel #3
0
static void
rx_b_frame(struct hfc4s8s_btype *bch)
{
	int z1, z2, hdlc_complete;
	u_char f1, f2;
	struct hfc4s8s_l1 *l1 = bch->l1p;
	struct sk_buff *skb;

	if (!l1->enabled || (bch->mode == L1_MODE_NULL))
		return;

	do {
		/* RX Fifo */
		Write_hfc8(l1->hw, R_FIFO,
			   (l1->st_num * 8 + ((bch->bchan == 1) ? 1 : 3)));
		wait_busy(l1->hw);

		if (bch->mode == L1_MODE_HDLC) {
			f1 = Read_hfc8_stable(l1->hw, A_F1);
			f2 = Read_hfc8(l1->hw, A_F2);
			hdlc_complete = ((f1 ^ f2) & MAX_F_CNT);
		} else
			hdlc_complete = 0;
		z1 = Read_hfc16_stable(l1->hw, A_Z1);
		z2 = Read_hfc16(l1->hw, A_Z2);
		z1 = (z1 - z2);
		if (hdlc_complete)
			z1++;
		if (z1 < 0)
			z1 += 384;

		if (!z1)
			break;

		if (!(skb = bch->rx_skb)) {
			if (!
			    (skb =
			     dev_alloc_skb((bch->mode ==
					    L1_MODE_TRANS) ? z1
					   : (MAX_B_FRAME_SIZE + 3)))) {
				printk(KERN_ERR
				       "HFC-4S/8S: Could not allocate B "
				       "channel receive buffer");
				return;
			}
			bch->rx_ptr = skb->data;
			bch->rx_skb = skb;
		}

		skb->len = (bch->rx_ptr - skb->data) + z1;

		/* HDLC length check */
		if ((bch->mode == L1_MODE_HDLC) &&
		    ((hdlc_complete && (skb->len < 4)) ||
		     (skb->len > (MAX_B_FRAME_SIZE + 3)))) {

			skb->len = 0;
			bch->rx_ptr = skb->data;
			Write_hfc8(l1->hw, A_INC_RES_FIFO, 2);	/* reset fifo */
			wait_busy(l1->hw);
			return;
		}
#ifndef HISAX_HFC4S8S_PCIMEM
		SetRegAddr(l1->hw, A_FIFO_DATA0);
#endif

		while (z1 >= 4) {
#ifdef HISAX_HFC4S8S_PCIMEM
			*((unsigned long *) bch->rx_ptr) =
			    Read_hfc32(l1->hw, A_FIFO_DATA0);
#else
			*((unsigned long *) bch->rx_ptr) =
			    fRead_hfc32(l1->hw);
#endif
			bch->rx_ptr += 4;
			z1 -= 4;
		}

		while (z1--)
#ifdef HISAX_HFC4S8S_PCIMEM
			*(bch->rx_ptr++) = Read_hfc8(l1->hw, A_FIFO_DATA0);
#else
			*(bch->rx_ptr++) = fRead_hfc8(l1->hw);
#endif

		if (hdlc_complete) {
			/* increment f counter */
			Write_hfc8(l1->hw, A_INC_RES_FIFO, 1);
			wait_busy(l1->hw);

			/* hdlc crc check */
			bch->rx_ptr--;
			if (*bch->rx_ptr) {
				skb->len = 0;
				bch->rx_ptr = skb->data;
				continue;
			}
			skb->len -= 3;
		}
		if (hdlc_complete || (bch->mode == L1_MODE_TRANS)) {
			bch->rx_skb = NULL;
			bch->rx_ptr = NULL;
			bch->b_if.ifc.l1l2(&bch->b_if.ifc,
					   PH_DATA | INDICATION, skb);
		}

	} while (1);
}				/* rx_b_frame */
Beispiel #4
0
static void
rx_d_frame(struct hfc4s8s_l1 *l1p, int ech)
{
	int z1, z2;
	u_char f1, f2, df;
	struct sk_buff *skb;
	u_char *cp;


	if (!l1p->enabled)
		return;
	do {
		/* E/D RX fifo */
		Write_hfc8(l1p->hw, R_FIFO,
			   (l1p->st_num * 8 + ((ech) ? 7 : 5)));
		wait_busy(l1p->hw);

		f1 = Read_hfc8_stable(l1p->hw, A_F1);
		f2 = Read_hfc8(l1p->hw, A_F2);
		df = f1 - f2;
		if ((f1 - f2) < 0)
			df = f1 - f2 + MAX_F_CNT + 1;


		if (!df) {
			return;	/* no complete frame in fifo */
		}

		z1 = Read_hfc16_stable(l1p->hw, A_Z1);
		z2 = Read_hfc16(l1p->hw, A_Z2);

		z1 = z1 - z2 + 1;
		if (z1 < 0)
			z1 += 384;

		if (!(skb = dev_alloc_skb(MAX_D_FRAME_SIZE))) {
			printk(KERN_INFO
			       "HFC-4S/8S: Could not allocate D/E "
			       "channel receive buffer");
			Write_hfc8(l1p->hw, A_INC_RES_FIFO, 2);
			wait_busy(l1p->hw);
			return;
		}

		if (((z1 < 4) || (z1 > MAX_D_FRAME_SIZE))) {
			if (skb)
				dev_kfree_skb(skb);
			/* remove errornous D frame */
			if (df == 1) {
				/* reset fifo */
				Write_hfc8(l1p->hw, A_INC_RES_FIFO, 2);
				wait_busy(l1p->hw);
				return;
			} else {
				/* read errornous D frame */

#ifndef HISAX_HFC4S8S_PCIMEM
				SetRegAddr(l1p->hw, A_FIFO_DATA0);
#endif

				while (z1 >= 4) {
#ifdef HISAX_HFC4S8S_PCIMEM
					Read_hfc32(l1p->hw, A_FIFO_DATA0);
#else
					fRead_hfc32(l1p->hw);
#endif
					z1 -= 4;
				}

				while (z1--)
#ifdef HISAX_HFC4S8S_PCIMEM
					Read_hfc8(l1p->hw, A_FIFO_DATA0);
#else
					fRead_hfc8(l1p->hw);
#endif

				Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1);
				wait_busy(l1p->hw);
				return;
			}
		}

		cp = skb->data;

#ifndef HISAX_HFC4S8S_PCIMEM
		SetRegAddr(l1p->hw, A_FIFO_DATA0);
#endif

		while (z1 >= 4) {
#ifdef HISAX_HFC4S8S_PCIMEM
			*((unsigned long *) cp) =
			    Read_hfc32(l1p->hw, A_FIFO_DATA0);
#else
			*((unsigned long *) cp) = fRead_hfc32(l1p->hw);
#endif
			cp += 4;
			z1 -= 4;
		}

		while (z1--)
#ifdef HISAX_HFC4S8S_PCIMEM
			*cp++ = Read_hfc8(l1p->hw, A_FIFO_DATA0);
#else
			*cp++ = fRead_hfc8(l1p->hw);
#endif

		Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1);	/* increment f counter */
		wait_busy(l1p->hw);

		if (*(--cp)) {
			dev_kfree_skb(skb);
		} else {
			skb->len = (cp - skb->data) - 2;
			if (ech)
				l1p->d_if.ifc.l1l2(&l1p->d_if.ifc,
						   PH_DATA_E | INDICATION,
						   skb);
			else
				l1p->d_if.ifc.l1l2(&l1p->d_if.ifc,
						   PH_DATA | INDICATION,
						   skb);
		}
	} while (1);
}				/* rx_d_frame */
static void
tx_d_frame(struct hfc4s8s_l1 *l1p)
{
	struct sk_buff *skb;
	u_char f1, f2;
	u_char *cp;
	long cnt;

	if (l1p->l1_state != 7)
		return;

	/*         */
	Write_hfc8(l1p->hw, R_FIFO, (l1p->st_num * 8 + 4));
	wait_busy(l1p->hw);

	f1 = Read_hfc8(l1p->hw, A_F1);
	f2 = Read_hfc8_stable(l1p->hw, A_F2);

	if ((f1 ^ f2) & MAX_F_CNT)
		return;		/*                      */

	if (l1p->tx_cnt > 0) {
		cnt = l1p->tx_cnt;
		l1p->tx_cnt = 0;
		l1p->d_if.ifc.l1l2(&l1p->d_if.ifc, PH_DATA | CONFIRM,
				   (void *) cnt);
	}

	if ((skb = skb_dequeue(&l1p->d_tx_queue))) {
		cp = skb->data;
		cnt = skb->len;
#ifndef HISAX_HFC4S8S_PCIMEM
		SetRegAddr(l1p->hw, A_FIFO_DATA0);
#endif

		while (cnt >= 4) {
#ifdef HISAX_HFC4S8S_PCIMEM
			fWrite_hfc32(l1p->hw, A_FIFO_DATA0,
				     *(unsigned long *) cp);
#else
			SetRegAddr(l1p->hw, A_FIFO_DATA0);
			fWrite_hfc32(l1p->hw, *(unsigned long *) cp);
#endif
			cp += 4;
			cnt -= 4;
		}

#ifdef HISAX_HFC4S8S_PCIMEM
		while (cnt--)
			fWrite_hfc8(l1p->hw, A_FIFO_DATA0, *cp++);
#else
		while (cnt--)
			fWrite_hfc8(l1p->hw, *cp++);
#endif

		l1p->tx_cnt = skb->truesize;
		Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1);	/*                     */
		wait_busy(l1p->hw);

		dev_kfree_skb(skb);
	}
}				/*            */