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

📄 hfc_2bds0.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	bcs->channel = st->l1.bc;	if (open_hfcstate(st->l1.hardware, bcs))		return (-1);	st->l1.bcs = bcs;	st->l2.l2l1 = hfc_l2l1;	setstack_manager(st);	bcs->st = st;	setstack_l1_B(st);	return (0);}static voidhfcd_bh(struct IsdnCardState *cs){	if (!cs)		return;	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {		switch (cs->dc.hfcd.ph_state) {			case (0):				l1_msg(cs, HW_RESET | INDICATION, NULL);				break;			case (3):				l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);				break;			case (8):				l1_msg(cs, HW_RSYNC | INDICATION, NULL);				break;			case (6):				l1_msg(cs, HW_INFO2 | INDICATION, NULL);				break;			case (7):				l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);				break;			default:				break;		}	}	if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))		DChannel_proc_rcv(cs);	if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))		DChannel_proc_xmt(cs);}staticint receive_dmsg(struct IsdnCardState *cs){	struct sk_buff *skb;	int idx;	int rcnt, z1, z2;	u_char stat, cip, f1, f2;	int chksum;	int count=5;	u_char *ptr;	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {		debugl1(cs, "rec_dmsg blocked");		return(1);	}	SelFiFo(cs, 4 | HFCD_REC);	cip = HFCD_FIFO | HFCD_F1 | HFCD_REC;	WaitNoBusy(cs);	f1 = cs->readisac(cs, cip) & 0xf;	cip = HFCD_FIFO | HFCD_F2 | HFCD_REC;	WaitNoBusy(cs);	f2 = cs->readisac(cs, cip) & 0xf;	while ((f1 != f2) && count--) {		z1 = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_REC);		z2 = ReadZReg(cs, HFCD_FIFO | HFCD_Z2 | HFCD_REC);		rcnt = z1 - z2;		if (rcnt < 0)			rcnt += cs->hw.hfcD.dfifosize;		rcnt++;		if (cs->debug & L1_DEB_ISAC)			debugl1(cs, "hfcd recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",				f1, f2, z1, z2, rcnt);		idx = 0;		cip = HFCD_FIFO | HFCD_FIFO_OUT | HFCD_REC;		if (rcnt > MAX_DFRAME_LEN + 3) {			if (cs->debug & L1_DEB_WARN)				debugl1(cs, "empty_fifo d: incoming packet too large");			while (idx < rcnt) {				if (!(WaitNoBusy(cs)))					break;				ReadReg(cs, HFCD_DATA_NODEB, cip);				idx++;			}		} else if (rcnt < 4) {			if (cs->debug & L1_DEB_WARN)				debugl1(cs, "empty_fifo d: incoming packet too small");			while ((idx++ < rcnt) && WaitNoBusy(cs))				ReadReg(cs, HFCD_DATA_NODEB, cip);		} else if ((skb = dev_alloc_skb(rcnt - 3))) {			ptr = skb_put(skb, rcnt - 3);			while (idx < (rcnt - 3)) {				if (!(WaitNoBusy(cs)))					break;				*ptr = ReadReg(cs, HFCD_DATA_NODEB, cip);				idx++;				ptr++;			}			if (idx != (rcnt - 3)) {				debugl1(cs, "RFIFO D BUSY error");				printk(KERN_WARNING "HFC DFIFO channel BUSY Error\n");				dev_kfree_skb_irq(skb);				skb = NULL;#ifdef ERROR_STATISTIC				cs->err_rx++;#endif			} else {				WaitNoBusy(cs);				chksum = (ReadReg(cs, HFCD_DATA, cip) << 8);				WaitNoBusy(cs);				chksum += ReadReg(cs, HFCD_DATA, cip);				WaitNoBusy(cs);				stat = ReadReg(cs, HFCD_DATA, cip);				if (cs->debug & L1_DEB_ISAC)					debugl1(cs, "empty_dfifo chksum %x stat %x",						chksum, stat);				if (stat) {					debugl1(cs, "FIFO CRC error");					dev_kfree_skb_irq(skb);					skb = NULL;#ifdef ERROR_STATISTIC					cs->err_crc++;#endif				} else {					skb_queue_tail(&cs->rq, skb);					schedule_event(cs, D_RCVBUFREADY);				}			}		} else			printk(KERN_WARNING "HFC: D receive out of memory\n");		WaitForBusy(cs);		cip = HFCD_FIFO | HFCD_F2_INC | HFCD_REC;		WaitNoBusy(cs);		stat = ReadReg(cs, HFCD_DATA, cip);		WaitForBusy(cs);		cip = HFCD_FIFO | HFCD_F2 | HFCD_REC;		WaitNoBusy(cs);		f2 = cs->readisac(cs, cip) & 0xf;	}	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);	return(1);} static voidhfc_fill_dfifo(struct IsdnCardState *cs){	int idx, fcnt;	int count;	u_char cip;	if (!cs->tx_skb)		return;	if (cs->tx_skb->len <= 0)		return;	SelFiFo(cs, 4 | HFCD_SEND);	cip = HFCD_FIFO | HFCD_F1 | HFCD_SEND;	WaitNoBusy(cs);	cs->hw.hfcD.f1 = ReadReg(cs, HFCD_DATA, cip) & 0xf;	WaitNoBusy(cs);	cip = HFCD_FIFO | HFCD_F2 | HFCD_SEND;	cs->hw.hfcD.f2 = ReadReg(cs, HFCD_DATA, cip) & 0xf;	cs->hw.hfcD.send[cs->hw.hfcD.f1] = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_SEND);	if (cs->debug & L1_DEB_ISAC)		debugl1(cs, "hfc_fill_Dfifo f1(%d) f2(%d) z1(%x)",			cs->hw.hfcD.f1, cs->hw.hfcD.f2,			cs->hw.hfcD.send[cs->hw.hfcD.f1]);	fcnt = cs->hw.hfcD.f1 - cs->hw.hfcD.f2;	if (fcnt < 0)		fcnt += 16;	if (fcnt > 14) {		if (cs->debug & L1_DEB_HSCX)			debugl1(cs, "hfc_fill_Dfifo more as 14 frames");		return;	}	count = GetFreeFifoBytes_D(cs);	if (cs->debug & L1_DEB_ISAC)		debugl1(cs, "hfc_fill_Dfifo count(%ld/%d)",			cs->tx_skb->len, count);	if (count < cs->tx_skb->len) {		if (cs->debug & L1_DEB_ISAC)			debugl1(cs, "hfc_fill_Dfifo no fifo mem");		return;	}	cip = HFCD_FIFO | HFCD_FIFO_IN | HFCD_SEND;	idx = 0;	WaitForBusy(cs);	WaitNoBusy(cs);	WriteReg(cs, HFCD_DATA_NODEB, cip, cs->tx_skb->data[idx++]);	while (idx < cs->tx_skb->len) {		if (!(WaitNoBusy(cs)))			break;		WriteReg(cs, HFCD_DATA_NODEB, cip, cs->tx_skb->data[idx]);		idx++;	}	if (idx != cs->tx_skb->len) {		debugl1(cs, "DFIFO Send BUSY error");		printk(KERN_WARNING "HFC S DFIFO channel BUSY Error\n");	}	WaitForBusy(cs);	WaitNoBusy(cs);	ReadReg(cs, HFCD_DATA, HFCD_FIFO | HFCD_F1_INC | HFCD_SEND);	dev_kfree_skb_any(cs->tx_skb);	cs->tx_skb = NULL;	WaitForBusy(cs);	return;}static struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel){	if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))		return(&cs->bcs[0]);	else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))		return(&cs->bcs[1]);	else		return(NULL);}voidhfc2bds0_interrupt(struct IsdnCardState *cs, u_char val){       	u_char exval;       	struct BCState *bcs;	int count=15;	if (cs->debug & L1_DEB_ISAC)		debugl1(cs, "HFCD irq %x %s", val,			test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?			"locked" : "unlocked");	val &= cs->hw.hfcD.int_m1;	if (val & 0x40) { /* TE state machine irq */		exval = cs->readisac(cs, HFCD_STATES) & 0xf;		if (cs->debug & L1_DEB_ISAC)			debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcd.ph_state,				exval);		cs->dc.hfcd.ph_state = exval;		schedule_event(cs, D_L1STATECHANGE);		val &= ~0x40;	}	while (val) {		if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {			cs->hw.hfcD.int_s1 |= val;			return;		}		if (cs->hw.hfcD.int_s1 & 0x18) {			exval = val;			val =  cs->hw.hfcD.int_s1;			cs->hw.hfcD.int_s1 = exval;		}			if (val & 0x08) {			if (!(bcs=Sel_BCS(cs, 0))) {				if (cs->debug)					debugl1(cs, "hfcd spurious 0x08 IRQ");			} else 				main_rec_2bds0(bcs);		}		if (val & 0x10) {			if (!(bcs=Sel_BCS(cs, 1))) {				if (cs->debug)					debugl1(cs, "hfcd spurious 0x10 IRQ");			} else 				main_rec_2bds0(bcs);		}		if (val & 0x01) {			if (!(bcs=Sel_BCS(cs, 0))) {				if (cs->debug)					debugl1(cs, "hfcd spurious 0x01 IRQ");			} else {				if (bcs->tx_skb) {					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {						hfc_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)) {							hfc_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, "hfcd spurious 0x02 IRQ");			} else {				if (bcs->tx_skb) {					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {						hfc_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)) {							hfc_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)) {						hfc_fill_dfifo(cs);						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);					} else {						debugl1(cs, "hfc_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)) {					hfc_fill_dfifo(cs);					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);				} else {					debugl1(cs, "hfc_fill_dfifo irq blocked");				}			} else				schedule_event(cs, D_XMTBUFREADY);		}      afterXPR:		if (cs->hw.hfcD.int_s1 && count--) {			val = cs->hw.hfcD.int_s1;			cs->hw.hfcD.int_s1 = 0;			if (cs->debug & L1_DEB_ISAC)				debugl1(cs, "HFCD irq %x loop %d", val, 15-count);		} else			val = 0;	}}static voidHFCD_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)) {					hfc_fill_dfifo(cs);					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);				} else					debugl1(cs, "hfc_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)) {				hfc_fill_dfifo(cs);				test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);			} else				debugl1(cs, "hfc_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);			cs->writeisac(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */			udelay(6);			cs->writeisac(cs, HFCD_STATES, 3); /* HFC ST 2 */			cs->hw.hfcD.mst_m |= HFCD_MASTER;			cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);			cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_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);			cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION);			spin_unlock_irqrestore(&cs->lock, flags);			break;		case (HW_DEACTIVATE | REQUEST):			spin_lock_irqsave(&cs->lock, flags);			cs->hw.hfcD.mst_m &= ~HFCD_MASTER;			cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);			spin_unlock_irqrestore(&cs->lock, flags);			break;		case (HW_INFO3 | REQUEST):			spin_lock_irqsave(&cs->lock, flags);			cs->hw.hfcD.mst_m |= HFCD_MASTER;			cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);			spin_unlock_irqrestore(&cs->lock, flags);			break;		default:			if (cs->debug & L1_DEB_WARN)				debugl1(cs, "hfcd_l1hw unknown pr %4x", pr);			break;	}}static voidsetstack_hfcd(struct PStack *st, struct IsdnCardState *cs){	st->l1.l1hw = HFCD_l1hw;}static voidhfc_dbusy_timer(struct IsdnCardState *cs){}static unsigned int __init*init_send_hfcd(int cnt){	int i, *send;	if (!(send = kmalloc(cnt * sizeof(unsigned int), GFP_ATOMIC))) {		printk(KERN_WARNING		       "HiSax: No memory for hfcd.send\n");		return(NULL);	}	for (i = 0; i < cnt; i++)		send[i] = 0x1fff;	return(send);}void __initinit2bds0(struct IsdnCardState *cs){	cs->setstack_d = setstack_hfcd;	if (!cs->hw.hfcD.send)		cs->hw.hfcD.send = init_send_hfcd(16);	if (!cs->bcs[0].hw.hfc.send)		cs->bcs[0].hw.hfc.send = init_send_hfcd(32);	if (!cs->bcs[1].hw.hfc.send)		cs->bcs[1].hw.hfc.send = init_send_hfcd(32);	cs->BC_Send_Data = &hfc_send_data;	cs->bcs[0].BC_SetStack = setstack_2b;	cs->bcs[1].BC_SetStack = setstack_2b;	cs->bcs[0].BC_Close = close_2bs0;	cs->bcs[1].BC_Close = close_2bs0;	mode_2bs0(cs->bcs, 0, 0);	mode_2bs0(cs->bcs + 1, 0, 1);}voidrelease2bds0(struct IsdnCardState *cs){	kfree(cs->bcs[0].hw.hfc.send);	cs->bcs[0].hw.hfc.send = NULL;	kfree(cs->bcs[1].hw.hfc.send);	cs->bcs[1].hw.hfc.send = NULL;	kfree(cs->hw.hfcD.send);	cs->hw.hfcD.send = NULL;}voidset_cs_func(struct IsdnCardState *cs){	cs->readisac = &readreghfcd;	cs->writeisac = &writereghfcd;	cs->readisacfifo = &dummyf;	cs->writeisacfifo = &dummyf;	cs->BC_Read_Reg = &ReadReg;	cs->BC_Write_Reg = &WriteReg;	cs->dbusytimer.function = (void *) hfc_dbusy_timer;	cs->dbusytimer.data = (long) cs;	init_timer(&cs->dbusytimer);	INIT_WORK(&cs->tqueue, (void *)(void *) hfcd_bh, cs);}

⌨️ 快捷键说明

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