⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hfc4s8s_l1.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 3 页
字号:
					wait_busy(l1->hw);					Write_hfc8(l1->hw, A_IRQ_MSK, 0);	/* disable TX interrupts */					wait_busy(l1->hw);					Write_hfc8(l1->hw, R_FIFO,						   (l1->st_num * 8 +						    ((bch->bchan ==						      1) ? 1 : 3)));					wait_busy(l1->hw);					Write_hfc8(l1->hw, A_IRQ_MSK, 0);	/* disable RX interrupts */					Write_hfc8(l1->hw, R_ST_SEL,						   l1->st_num);					l1->hw->mr.r_ctrl0 &=					    ~(bch->bchan & 3);					Write_hfc8(l1->hw, A_ST_CTRL0,						   l1->hw->mr.r_ctrl0);					spin_unlock_irqrestore(&l1->lock,							       flags);					bch->mode = L1_MODE_NULL;					bch->b_if.ifc.l1l2(&bch->b_if.ifc,							   PH_DEACTIVATE |							   INDICATION,							   NULL);					if (bch->tx_skb) {						dev_kfree_skb(bch->tx_skb);						bch->tx_skb = NULL;					}					if (bch->rx_skb) {						dev_kfree_skb(bch->rx_skb);						bch->rx_skb = NULL;					}					skb_queue_purge(&bch->tx_queue);					bch->tx_cnt = 0;					bch->rx_ptr = NULL;					break;			}			/* timer is only used when at least one b channel */			/* is set up to transparent mode */			if (l1->hw->mr.timer_usg_cnt) {				Write_hfc8(l1->hw, R_IRQMSK_MISC,					   M_TI_IRQMSK);			} else {				Write_hfc8(l1->hw, R_IRQMSK_MISC, 0);			}			break;		default:			printk(KERN_INFO			       "HFC-4S/8S: Unknown B-chan cmd 0x%x received, ignored\n",			       pr);			break;	}	if (!l1->enabled)		bch->b_if.ifc.l1l2(&bch->b_if.ifc,				   PH_DEACTIVATE | INDICATION, NULL);}				/* bch_l2l1 *//**************************//* layer 1 timer function *//**************************/static voidhfc_l1_timer(struct hfc4s8s_l1 *l1){	u_long flags;	if (!l1->enabled)		return;	spin_lock_irqsave(&l1->lock, flags);	if (l1->nt_mode) {		l1->l1_state = 1;		Write_hfc8(l1->hw, R_ST_SEL, l1->st_num);		Write_hfc8(l1->hw, A_ST_WR_STA, 0x11);		spin_unlock_irqrestore(&l1->lock, flags);		l1->d_if.ifc.l1l2(&l1->d_if.ifc,				  PH_DEACTIVATE | INDICATION, NULL);		spin_lock_irqsave(&l1->lock, flags);		l1->l1_state = 1;		Write_hfc8(l1->hw, A_ST_WR_STA, 0x1);		spin_unlock_irqrestore(&l1->lock, flags);	} else {		/* activation timed out */		Write_hfc8(l1->hw, R_ST_SEL, l1->st_num);		Write_hfc8(l1->hw, A_ST_WR_STA, 0x13);		spin_unlock_irqrestore(&l1->lock, flags);		l1->d_if.ifc.l1l2(&l1->d_if.ifc,				  PH_DEACTIVATE | INDICATION, NULL);		spin_lock_irqsave(&l1->lock, flags);		Write_hfc8(l1->hw, R_ST_SEL, l1->st_num);		Write_hfc8(l1->hw, A_ST_WR_STA, 0x3);		spin_unlock_irqrestore(&l1->lock, flags);	}}				/* hfc_l1_timer *//****************************************//* a complete D-frame has been received *//****************************************/static voidrx_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 CONFIG_HISAX_HFC4S8S_PCIMEM				SetRegAddr(l1p->hw, A_FIFO_DATA0);#endif				while (z1 >= 4) {#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM					Read_hfc32(l1p->hw, A_FIFO_DATA0);#else					fRead_hfc32(l1p->hw);#endif					z1 -= 4;				}				while (z1--)#ifdef CONFIG_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 CONFIG_HISAX_HFC4S8S_PCIMEM		SetRegAddr(l1p->hw, A_FIFO_DATA0);#endif		while (z1 >= 4) {#ifdef CONFIG_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 CONFIG_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 *//*************************************************************//* a B-frame has been received (perhaps not fully completed) *//*************************************************************/static voidrx_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 CONFIG_HISAX_HFC4S8S_PCIMEM		SetRegAddr(l1->hw, A_FIFO_DATA0);#endif		while (z1 >= 4) {#ifdef CONFIG_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 CONFIG_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 *//********************************************//* a D-frame has been/should be transmitted *//********************************************/static voidtx_d_frame(struct hfc4s8s_l1 *l1p){	struct sk_buff *skb;	u_char f1, f2;	u_char *cp;	int 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;#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM		SetRegAddr(l1p->hw, A_FIFO_DATA0);#endif		while (cnt >= 4) {#ifdef CONFIG_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 CONFIG_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);	/* increment f counter */		wait_busy(l1p->hw);		dev_kfree_skb(skb);	}}				/* tx_d_frame *//******************************************************//* a B-frame may be transmitted (or is not completed) *//******************************************************/static voidtx_b_frame(struct hfc4s8s_btype *bch){	struct sk_buff *skb;	struct hfc4s8s_l1 *l1 = bch->l1p;	u_char *cp;	int cnt, max, hdlc_num, 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 CONFIG_HISAX_HFC4S8S_PCIMEM		SetRegAddr(l1->hw, A_FIFO_DATA0);#endif		while (cnt >= 4) {#ifdef CONFIG_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 CONFIG_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 = 0;			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 *//*************************************//* bottom half handler for interrupt *//*************************************/static voidhfc4s8s_bh(hfc4s8s_hw * hw){	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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -