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

📄 hfc_sx.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
{	if (!cs->tx_skb)		return;	if (cs->tx_skb->len <= 0)		return;	if (write_fifo(cs, cs->tx_skb, HFCSX_SEL_D_TX, 0)) {	  dev_kfree_skb_any(cs->tx_skb);	  cs->tx_skb = NULL;	}	return;}/**************************//* B-channel send routine *//**************************/static voidhfcsx_fill_fifo(struct BCState *bcs){	struct IsdnCardState *cs = bcs->cs;	if (!bcs->tx_skb)		return;	if (bcs->tx_skb->len <= 0)		return;	if (write_fifo(cs, bcs->tx_skb, 		       ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ? 		       HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX,		       (bcs->mode == L1_MODE_TRANS) ? 		       HFCSX_BTRANS_THRESHOLD : 0)) {	  bcs->tx_cnt -= bcs->tx_skb->len;	  if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&		(PACKET_NOACK != bcs->tx_skb->pkt_type)) {		u_long	flags;		spin_lock_irqsave(&bcs->aclock, flags);		bcs->ackcnt += bcs->tx_skb->len;		spin_unlock_irqrestore(&bcs->aclock, flags);		schedule_event(bcs, B_ACKPENDING);	  }	  dev_kfree_skb_any(bcs->tx_skb);	  bcs->tx_skb = NULL;	  test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);	}}/**********************************************//* D-channel l1 state call for leased NT-mode *//**********************************************/static voiddch_nt_l2l1(struct PStack *st, int pr, void *arg){	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;	switch (pr) {		case (PH_DATA | REQUEST):		case (PH_PULL | REQUEST):		case (PH_PULL | INDICATION):			st->l1.l1hw(st, pr, arg);			break;		case (PH_ACTIVATE | REQUEST):			st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);			break;		case (PH_TESTLOOP | REQUEST):			if (1 & (long) arg)				debugl1(cs, "PH_TEST_LOOP B1");			if (2 & (long) arg)				debugl1(cs, "PH_TEST_LOOP B2");			if (!(3 & (long) arg))				debugl1(cs, "PH_TEST_LOOP DISABLED");			st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg);			break;		default:			if (cs->debug)				debugl1(cs, "dch_nt_l2l1 msg %04X unhandled", pr);			break;	}}/***********************//* set/reset echo mode *//***********************/static inthfcsx_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic){	unsigned long flags;	int i = *(unsigned int *) ic->parm.num;	if ((ic->arg == 98) &&	    (!(cs->hw.hfcsx.int_m1 & (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC + HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC)))) {	    	spin_lock_irqsave(&cs->lock, flags);		Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 0);	/* HFC ST G0 */		udelay(10);		cs->hw.hfcsx.sctrl |= SCTRL_MODE_NT;		Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);	/* set NT-mode */		udelay(10);		Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 1);	/* HFC ST G1 */		udelay(10);		Write_hfc(cs, HFCSX_STATES, 1 | HFCSX_ACTIVATE | HFCSX_DO_ACTION);		cs->dc.hfcsx.ph_state = 1;		cs->hw.hfcsx.nt_mode = 1;		cs->hw.hfcsx.nt_timer = 0;		spin_unlock_irqrestore(&cs->lock, flags);		cs->stlist->l2.l2l1 = dch_nt_l2l1;		debugl1(cs, "NT mode activated");		return (0);	}	if ((cs->chanlimit > 1) || (cs->hw.hfcsx.bswapped) ||	    (cs->hw.hfcsx.nt_mode) || (ic->arg != 12))		return (-EINVAL);	if (i) {		cs->logecho = 1;		cs->hw.hfcsx.trm |= 0x20;	/* enable echo chan */		cs->hw.hfcsx.int_m1 |= HFCSX_INTS_B2REC;		/* reset Channel !!!!! */	} else {		cs->logecho = 0;		cs->hw.hfcsx.trm &= ~0x20;	/* disable echo chan */		cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_B2REC;	}	cs->hw.hfcsx.sctrl_r &= ~SCTRL_B2_ENA;	cs->hw.hfcsx.sctrl &= ~SCTRL_B2_ENA;	cs->hw.hfcsx.conn |= 0x10;	/* B2-IOM -> B2-ST */	cs->hw.hfcsx.ctmt &= ~2;	spin_lock_irqsave(&cs->lock, flags);	Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt);	Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r);	Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);	Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);	Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);	spin_unlock_irqrestore(&cs->lock, flags);	return (0);}				/* hfcsx_auxcmd *//*****************************//* E-channel receive routine *//*****************************/static voidreceive_emsg(struct IsdnCardState *cs){	int count = 5;	u_char *ptr;	struct sk_buff *skb;	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {		debugl1(cs, "echo_rec_data blocked");		return;	}	do {	  skb = read_fifo(cs, HFCSX_SEL_B2_RX, 0);	  if (skb) {	    if (cs->debug & DEB_DLOG_HEX) {	      ptr = cs->dlog;	      if ((skb->len) < MAX_DLOG_SPACE / 3 - 10) {		*ptr++ = 'E';		*ptr++ = 'C';		*ptr++ = 'H';		*ptr++ = 'O';		*ptr++ = ':';		ptr += QuickHex(ptr, skb->data, skb->len);		ptr--;		*ptr++ = '\n';		*ptr = 0;		HiSax_putstatus(cs, NULL, cs->dlog);	      } else		HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", skb->len);	    }	    dev_kfree_skb_any(skb);	  }	} while (--count && skb);	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);	return;}				/* receive_emsg *//*********************//* Interrupt handler *//*********************/static irqreturn_thfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs){	struct IsdnCardState *cs = dev_id;	u_char exval;	struct BCState *bcs;	int count = 15;	u_long flags;	u_char val, stat;	if (!(cs->hw.hfcsx.int_m2 & 0x08))		return IRQ_NONE;		/* not initialised */	spin_lock_irqsave(&cs->lock, flags);	if (HFCSX_ANYINT & (stat = Read_hfc(cs, HFCSX_STATUS))) {		val = Read_hfc(cs, HFCSX_INT_S1);		if (cs->debug & L1_DEB_ISAC)			debugl1(cs, "HFC-SX: stat(%02x) s1(%02x)", stat, val);	} else {		spin_unlock_irqrestore(&cs->lock, flags);		return IRQ_NONE;	}	if (cs->debug & L1_DEB_ISAC)		debugl1(cs, "HFC-SX irq %x %s", val,			test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?			"locked" : "unlocked");	val &= cs->hw.hfcsx.int_m1;	if (val & 0x40) {	/* state machine irq */		exval = Read_hfc(cs, HFCSX_STATES) & 0xf;		if (cs->debug & L1_DEB_ISAC)			debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcsx.ph_state,				exval);		cs->dc.hfcsx.ph_state = exval;		schedule_event(cs, D_L1STATECHANGE);		val &= ~0x40;	}	if (val & 0x80) {	/* timer irq */		if (cs->hw.hfcsx.nt_mode) {			if ((--cs->hw.hfcsx.nt_timer) < 0)				schedule_event(cs, D_L1STATECHANGE);		}		val &= ~0x80;		Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER);	}	while (val) {		if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {			cs->hw.hfcsx.int_s1 |= val;			spin_unlock_irqrestore(&cs->lock, flags);			return IRQ_HANDLED;		}		if (cs->hw.hfcsx.int_s1 & 0x18) {			exval = val;			val = cs->hw.hfcsx.int_s1;			cs->hw.hfcsx.int_s1 = exval;		}		if (val & 0x08) {			if (!(bcs = Sel_BCS(cs, cs->hw.hfcsx.bswapped ? 1 : 0))) {				if (cs->debug)					debugl1(cs, "hfcsx spurious 0x08 IRQ");			} else				main_rec_hfcsx(bcs);		}		if (val & 0x10) {			if (cs->logecho)				receive_emsg(cs);			else if (!(bcs = Sel_BCS(cs, 1))) {				if (cs->debug)					debugl1(cs, "hfcsx spurious 0x10 IRQ");			} else				main_rec_hfcsx(bcs);		}		if (val & 0x01) {			if (!(bcs = Sel_BCS(cs, cs->hw.hfcsx.bswapped ? 1 : 0))) {				if (cs->debug)					debugl1(cs, "hfcsx spurious 0x01 IRQ");			} else {				if (bcs->tx_skb) {					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {						hfcsx_fill_fifo(bcs);						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);					} else						debugl1(cs, "fill_data %d blocked", bcs->channel);				} else {					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {							hfcsx_fill_fifo(bcs);							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);						} else							debugl1(cs, "fill_data %d blocked", bcs->channel);					} else {						schedule_event(bcs, B_XMTBUFREADY);					}				}			}		}		if (val & 0x02) {			if (!(bcs = Sel_BCS(cs, 1))) {				if (cs->debug)					debugl1(cs, "hfcsx spurious 0x02 IRQ");			} else {				if (bcs->tx_skb) {					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {						hfcsx_fill_fifo(bcs);						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);					} else						debugl1(cs, "fill_data %d blocked", bcs->channel);				} else {					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {							hfcsx_fill_fifo(bcs);							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);						} else							debugl1(cs, "fill_data %d blocked", bcs->channel);					} else {						schedule_event(bcs, B_XMTBUFREADY);					}				}			}		}		if (val & 0x20) {	/* receive dframe */			receive_dmsg(cs);		}		if (val & 0x04) {	/* dframe transmitted */			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))				del_timer(&cs->dbusytimer);			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))				schedule_event(cs, D_CLEARBUSY);			if (cs->tx_skb) {				if (cs->tx_skb->len) {					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {						hfcsx_fill_dfifo(cs);						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);					} else {						debugl1(cs, "hfcsx_fill_dfifo irq blocked");					}					goto afterXPR;				} else {					dev_kfree_skb_irq(cs->tx_skb);					cs->tx_cnt = 0;					cs->tx_skb = NULL;				}			}			if ((cs->tx_skb = skb_dequeue(&cs->sq))) {				cs->tx_cnt = 0;				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {					hfcsx_fill_dfifo(cs);					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);				} else {					debugl1(cs, "hfcsx_fill_dfifo irq blocked");				}			} else				schedule_event(cs, D_XMTBUFREADY);		}	      afterXPR:		if (cs->hw.hfcsx.int_s1 && count--) {			val = cs->hw.hfcsx.int_s1;			cs->hw.hfcsx.int_s1 = 0;			if (cs->debug & L1_DEB_ISAC)				debugl1(cs, "HFC-SX irq %x loop %d", val, 15 - count);		} else			val = 0;	}	spin_unlock_irqrestore(&cs->lock, flags);	return IRQ_HANDLED;}/********************************************************************//* timer callback for D-chan busy resolution. Currently no function *//********************************************************************/static voidhfcsx_dbusy_timer(struct IsdnCardState *cs){}/*************************************//* Layer 1 D-channel hardware access *//*************************************/static voidHFCSX_l1hw(struct PStack *st, int pr, void *arg){	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;	struct sk_buff *skb = arg;	u_long flags;	switch (pr) {		case (PH_DATA | REQUEST):			if (cs->debug & DEB_DLOG_HEX)				LogFrame(cs, skb->data, skb->len);			if (cs->debug & DEB_DLOG_VERBOSE)				dlogframe(cs, skb, 0);			spin_lock_irqsave(&cs->lock, flags);			if (cs->tx_skb) {				skb_queue_tail(&cs->sq, skb);#ifdef L2FRAME_DEBUG		/* psa */				if (cs->debug & L1_DEB_LAPD)					Logl2Frame(cs, skb, "PH_DATA Queued", 0);#endif			} else {				cs->tx_skb = skb;				cs->tx_cnt = 0;#ifdef L2FRAME_DEBUG		/* psa */				if (cs->debug & L1_DEB_LAPD)					Logl2Frame(cs, skb, "PH_DATA", 0);#endif				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {				        hfcsx_fill_dfifo(cs); 					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);				} else					debugl1(cs, "hfcsx_fill_dfifo blocked");			}			spin_unlock_irqrestore(&cs->lock, flags);			break;		case (PH_PULL | INDICATION):			spin_lock_irqsave(&cs->lock, flags);			if (cs->tx_skb) {				if (cs->debug & L1_DEB_WARN)					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");				skb_queue_tail(&cs->sq, skb);				spin_unlock_irqrestore(&cs->lock, flags);				break;			}			if (cs->debug & DEB_DLOG_HEX)				LogFrame(cs, skb->data, skb->len);			if (cs->debug & DEB_DLOG_VERBOSE)				dlogframe(cs, skb, 0);			cs->tx_skb = skb;			cs->tx_cnt = 0;#ifdef L2FRAME_DEBUG		/* psa */			if (cs->debug & L1_DEB_LAPD)				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);#endif			if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {				hfcsx_fill_dfifo(cs); 				test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);			} else				debugl1(cs, "hfcsx_fill_dfifo blocked");			spin_unlock_irqrestore(&cs->lock, flags);			break;		case (PH_PULL | REQUEST):#ifdef L2FRAME_DEBUG		/* psa */			if (cs->debug & L1_DEB_LAPD)				debugl1(cs, "-> PH_REQUEST_PULL");#endif			if (!cs->tx_skb) {				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);			} else				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);			break;		case (HW_RESET | REQUEST):			spin_lock_irqsave(&cs->lock, flags);			Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 3);	/* HFC ST 3 */			udelay(6);			Write_hfc(cs, HFCSX_STATES, 3);	/* HFC ST 2 */			cs->hw.hfcsx.mst_m |= HFCSX_MASTER;			Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);			Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION);			spin_unlock_irqrestore(&cs->lock, flags);			l1_msg(cs, HW_POWERUP | CONFIRM, NULL);			break;		case (HW_ENABLE | REQUEST):			spin_lock_irqsave(&cs->lock, flags);			Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION);			spin_unlock_irqrestore(&cs->lock, flags);			break;		case (HW_DEACTIVATE | REQUEST):			spin_lock_irqsave(&cs->lock, flags);			cs->hw.hfcsx.mst_m &= ~HFCSX_MASTER;			Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);			spin_unlock_irqrestore(&cs->lock, flags);			break;		case (HW_INFO3 | REQUEST):			spin_lock_irqsave(&cs->lock, flags);			cs->hw.hfcsx.mst_m |= HFCSX_MASTER;			Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);			spin_unlock_irqrestore(&cs->lock, flags);			break;		case (HW_TESTLOOP | REQUEST):			spin_lock_irqsave(&cs->lock, flags);			switch ((int) arg) {				case (1):					Write_hfc(cs, HFCSX_B1_SSL, 0x80);	/* tx slot */					Write_hfc(cs, HFCSX_B1_RSL, 0x80);	/* rx slot */					cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~7) | 1;					Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);					break;				case (2):					Write_hfc(cs, HFCSX_B2_SSL, 0x81);	/* tx slot */					Write_hfc(cs, HFCSX_B2_RSL, 0x81);	/* rx slot */					cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~0x38) | 0x08;					Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);					break;				default:					spin_unlock_irqrestore(&cs->lock, flags);					if (cs->debug & L1_DEB_WARN)						debugl1(cs, "hfcsx_l1hw loop invalid %4x", (int) arg);					return;			}			cs->hw.hfcsx.trm |= 0x80;	/* enable IOM-loop */			Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);			spin_unlock_irqrestore(&cs->lock, flags);			break;		default:			if (cs->debug & L1_DEB_WARN)				debugl1(cs, "hfcsx_l1hw unknown pr %4x", pr);			break;	}}/***********************************************//* called during init setting l1 stack pointer *//***********************************************/static voidsetstack_hfcsx(struct PStack *st, struct IsdnCardState *cs){	st->l1.l1hw = HFCSX_l1hw;}/**************************************//* send B-channel data if not blocked *//**************************************/static voidhfcsx_send_data(struct BCState *bcs)

⌨️ 快捷键说明

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