示例#1
0
static u_char
Read_hfc8_stable(hfc4s8s_hw * hw, int reg)
{
	u_char ref8;
	u_char in8;
	ref8 = Read_hfc8(hw, reg);
	while (((in8 = Read_hfc8(hw, reg)) != ref8)) {
		ref8 = in8;
	}
	return in8;
}
示例#2
0
static irqreturn_t
hfc4s8s_interrupt(int intno, void *dev_id)
{
	hfc4s8s_hw *hw = dev_id;
	u_char b, ovr;
	volatile u_char *ovp;
	int idx;
	u_char old_ioreg;

	if (!hw || !(hw->mr.r_irq_ctrl & M_GLOB_IRQ_EN))
		return IRQ_NONE;

#ifndef	HISAX_HFC4S8S_PCIMEM
	/* read current selected regsister */
	old_ioreg = GetRegAddr(hw);
#endif

	/* Layer 1 State change */
	hw->mr.r_irq_statech |=
	    (Read_hfc8(hw, R_SCI) & hw->mr.r_irqmsk_statchg);
	if (!
	    (b = (Read_hfc8(hw, R_STATUS) & (M_MISC_IRQSTA | M_FR_IRQSTA)))
&& !hw->mr.r_irq_statech) {
#ifndef	HISAX_HFC4S8S_PCIMEM
		SetRegAddr(hw, old_ioreg);
#endif
		return IRQ_NONE;
	}

	/* timer event */
	if (Read_hfc8(hw, R_IRQ_MISC) & M_TI_IRQ) {
		hw->mr.timer_irq = 1;
		hw->fifo_sched_cnt--;
	}

	/* FIFO event */
	if ((ovr = Read_hfc8(hw, R_IRQ_OVIEW))) {
		hw->mr.r_irq_oview |= ovr;
		idx = R_IRQ_FIFO_BL0;
		ovp = hw->mr.r_irq_fifo_blx;
		while (ovr) {
			if ((ovr & 1)) {
				*ovp |= Read_hfc8(hw, idx);
			}
			ovp++;
			idx++;
			ovr >>= 1;
		}
	}
示例#3
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 */
示例#4
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 */
示例#5
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 */
示例#6
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 */
示例#7
0
static void
hfc4s8s_bh(struct work_struct *work)
{
	hfc4s8s_hw *hw = container_of(work, hfc4s8s_hw, tqueue);
	u_char b;
	struct hfc4s8s_l1 *l1p;
	volatile u_char *fifo_stat;
	int idx;

	/* handle layer 1 state changes */
	b = 1;
	l1p = hw->l1;
	while (b) {
		if ((b & hw->mr.r_irq_statech)) {
			/* reset l1 event */
			hw->mr.r_irq_statech &= ~b;
			if (l1p->enabled) {
				if (l1p->nt_mode) {
					u_char oldstate = l1p->l1_state;

					Write_hfc8(l1p->hw, R_ST_SEL,
						   l1p->st_num);
					l1p->l1_state =
					    Read_hfc8(l1p->hw,
						      A_ST_RD_STA) & 0xf;

					if ((oldstate == 3)
					    && (l1p->l1_state != 3))
						l1p->d_if.ifc.l1l2(&l1p->
								   d_if.
								   ifc,
								   PH_DEACTIVATE
								   |
								   INDICATION,
								   NULL);

					if (l1p->l1_state != 2) {
						del_timer(&l1p->l1_timer);
						if (l1p->l1_state == 3) {
							l1p->d_if.ifc.
							    l1l2(&l1p->
								 d_if.ifc,
								 PH_ACTIVATE
								 |
								 INDICATION,
								 NULL);
						}
					} else {
						/* allow transition */
						Write_hfc8(hw, A_ST_WR_STA,
							   M_SET_G2_G3);
						mod_timer(&l1p->l1_timer,
							  jiffies +
							  L1_TIMER_T1);
					}
					printk(KERN_INFO
					       "HFC-4S/8S: NT ch %d l1 state %d -> %d\n",
					       l1p->st_num, oldstate,
					       l1p->l1_state);
				} else {
					u_char oldstate = l1p->l1_state;

					Write_hfc8(l1p->hw, R_ST_SEL,
						   l1p->st_num);
					l1p->l1_state =
					    Read_hfc8(l1p->hw,
						      A_ST_RD_STA) & 0xf;

					if (((l1p->l1_state == 3) &&
					     ((oldstate == 7) ||
					      (oldstate == 8))) ||
					    ((timer_pending
					      (&l1p->l1_timer))
					     && (l1p->l1_state == 8))) {
						mod_timer(&l1p->l1_timer,
							  L1_TIMER_T4 +
							  jiffies);
					} else {
						if (l1p->l1_state == 7) {
							del_timer(&l1p->
								  l1_timer);
							l1p->d_if.ifc.
							    l1l2(&l1p->
								 d_if.ifc,
								 PH_ACTIVATE
								 |
								 INDICATION,
								 NULL);
							tx_d_frame(l1p);
						}
						if (l1p->l1_state == 3) {
							if (oldstate != 3)
								l1p->d_if.
								    ifc.
								    l1l2
								    (&l1p->
								     d_if.
								     ifc,
								     PH_DEACTIVATE
								     |
								     INDICATION,
								     NULL);
						}
					}
					printk(KERN_INFO
					       "HFC-4S/8S: TE %d ch %d l1 state %d -> %d\n",
					       l1p->hw->cardnum,
					       l1p->st_num, oldstate,
					       l1p->l1_state);
				}
			}
		}
		b <<= 1;
		l1p++;
	}

	/* now handle the fifos */
	idx = 0;
	fifo_stat = hw->mr.r_irq_fifo_blx;
	l1p = hw->l1;
	while (idx < hw->driver_data.max_st_ports) {

		if (hw->mr.timer_irq) {
			*fifo_stat |= hw->mr.fifo_rx_trans_enables[idx];
			if (hw->fifo_sched_cnt <= 0) {
				*fifo_stat |=
				    hw->mr.fifo_slow_timer_service[l1p->
								   st_num];
			}
		}
		/* ignore fifo 6 (TX E fifo) */
		*fifo_stat &= 0xff - 0x40;

		while (*fifo_stat) {

			if (!l1p->nt_mode) {
				/* RX Fifo has data to read */
				if ((*fifo_stat & 0x20)) {
					*fifo_stat &= ~0x20;
					rx_d_frame(l1p, 0);
				}
				/* E Fifo has data to read */
				if ((*fifo_stat & 0x80)) {
					*fifo_stat &= ~0x80;
					rx_d_frame(l1p, 1);
				}
				/* TX Fifo completed send */
				if ((*fifo_stat & 0x10)) {
					*fifo_stat &= ~0x10;
					tx_d_frame(l1p);
				}
			}
			/* B1 RX Fifo has data to read */
			if ((*fifo_stat & 0x2)) {
				*fifo_stat &= ~0x2;
				rx_b_frame(l1p->b_ch);
			}
			/* B1 TX Fifo has send completed */
			if ((*fifo_stat & 0x1)) {
				*fifo_stat &= ~0x1;
				tx_b_frame(l1p->b_ch);
			}
			/* B2 RX Fifo has data to read */
			if ((*fifo_stat & 0x8)) {
				*fifo_stat &= ~0x8;
				rx_b_frame(l1p->b_ch + 1);
			}
			/* B2 TX Fifo has send completed */
			if ((*fifo_stat & 0x4)) {
				*fifo_stat &= ~0x4;
				tx_b_frame(l1p->b_ch + 1);
			}
		}
		fifo_stat++;
		l1p++;
		idx++;
	}

	if (hw->fifo_sched_cnt <= 0)
		hw->fifo_sched_cnt += (1 << (7 - TRANS_TIMER_MODE));
	hw->mr.timer_irq = 0;	/* clear requested timer irq */
}				/* hfc4s8s_bh */
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);
	}
}				/*            */